2010-09-03 22 views
6

Esta porción XSD se obtuvo de: http://www.iana.org/assignments/xml-registry/schema/netconf.xsdXSD Formateo <element><complexType> vs <complexType /><element/>

<xs:complexType name="rpcType"> 
    <xs:sequence> 
    <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
</xs:complexType> 
<xs:element name="rpc" type="rpcType"/> 

Y es el núcleo para funcionar llamadas en NETCONF siendo el nodo de un documento XML. Soy curioso en cuanto a por qué no es algo como:

<xs:element name="rpcType"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
    </xs:complexType> 
</xs:element> 

El razonamiento es que en el # 1 cuando se trata de ordenar de un grano (en jaxb2) consigo la excepción:

[com.sun.istack.SAXException2: unable to marshal type "netconf.RpcType" as an element because it is missing an @XmlRootElement annotation] 

tengo estado leyendo el artículo this una y otra vez, y realmente no puedo entender la diferencia, y por qué sería # 1 vs # 2 ...

Respuesta

1

Una pregunta bastante complicada. Existen muchas razones para diseñar esquemas utilizando tipos en lugar de elementos (este enfoque se denomina enfoque "ciego veneciano" frente a "sector salami" para usar elementos globales). Una de las razones es que los tipos pueden subtipificarse, y otro que puede ser útil tener solo elementos globales que pueden ser elementos raíz.

Consulte this article para obtener más detalles sobre el lado del esquema.

Ahora, en cuanto a la pregunta de JAXB en particular. El problema es que creó una clase correspondiente a un tipo e intentó serializarla. Eso significa que JAXB conoce su modelo de contenido, pero no cuál debería ser el nombre del elemento. Es necesario adjuntar su RpcType a un elemento (JAXBElement), por ejemplo:

marshaller.marshal(new ObjectFactory().createRpc(myRpcType)); 

El ObjectFactory se colocó en el paquete creado por JAXB para usted.

11

No es obvio, te lo concederé. Todo se reduce a la decisión tipo vs elemento.

Cuando usted tiene algo así como

<xs:element name="rpcType"> 
    <xs:complexType> 

Este es esencialmente un "tipo anónimo", y es un tipo que nunca puede ocurrir en cualquier lugar que no sea en el interior del elemento de rpcType. Debido a esta certeza, XJC sabe que ese tipo siempre tendrá el nombre rpcType, por lo que genera una anotación @XmlRootElement, con el nombre rpcType.

Por otro lado, cuando se tiene

<xs:complexType name="rpcType"> 

entonces esto define un tipo reutilizable que potencialmente podría denominar de varios elementos diferentes. El hecho de que en su esquema solo se refiera a un elemento es irrelevante. Debido a esta incertidumbre, XJC cubre sus apuestas y no genera un @XmlRootElement.

La implementación de referencia de JAXB tiene una marca XJC patentada llamada "simple binding mode" que, entre otras cosas, asume que el esquema que está compilando nunca se ampliará ni se combinará con otro. Esto le permite hacer ciertas suposiciones, por lo que si ve que un nombre complexType solo está siendo utilizado por un element, a menudo generará @XmlRootElement para él.

La realidad es bastante más sutil y compleja que eso, pero en el 90% de los casos, esta es una explicación suficiente.

+0

Si al usar 'modo de enlace simple', el xsd se extiende o combina, y otro elemento raíz se define con el mismo tipo (en la extensión) habrá un error de tiempo de compilación XJC, o un error de tiempo de ejecución o comportamiento indeterminado ? – Vihung

1

Ventajas de tipos con nombre

La ventaja de un esquema utilizando tipos globales/nombradas es que los tipos de niño/sub pueden ser creados que se extienden del tipo de los padres.

<xs:complexType name="rpcType"> 
    <xs:sequence> 
     <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
</xs:complexType> 
<xs:element name="rpc" type="rpcType"/> 

El fragmento anterior sería permitir que el siguiente tipo de niño que se cree:

<xs:complexType name="myRPCType"> 
    <xs:complexContent> 
     <xs:extension base="rpcType"> 
      <xs:sequence> 
       <xs:element name="childProperty" type="xs:string"/> 
      </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

Impacto en JAXB

Otro aspecto de tipos con nombre es que pueden ser utilizados por los múltiples elementos :

<xs:element name="FOO" type="rpcType"/> 
<xs:element name="BAR" type="rpcType"/> 

Esto significa t El esquema del compilador Java no puede simplemente elegir uno de los elementos posibles para ser @XmlRootElement para la clase correspondiente a "rpcType".