2010-09-03 14 views
6

Dieser XSD Teil wurde aus: http://www.iana.org/assignments/xml-registry/schema/netconf.xsdXSD Formatierung <element><complexType> vs <complex /><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"/> 

Und ist der Kern Anrufe in NETCONF ist der Knoten eines XML-Dokuments funktionieren. Ich bin neugierig, warum ist es nicht so etwas wie:

<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> 

Die Argumentation ist, dass 1 in #, wenn sie marshall eine Bohne (in jaxb2) versuche ich die Ausnahme erhalten:

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

Ich habe this Artikel immer und immer wieder gelesen, und kann wirklich nicht den Unterschied zu fassen, und warum es wäre # 1 vs # 2 ...

Antwort

1

Ziemlich eine Frage beteiligt. Es gibt viele Gründe, Schemas mit Typen anstelle von Elementen zu entwerfen (dieser Ansatz wird als "Jalousie" -Ansatz gegenüber "Salami-Slice" zur Verwendung globaler Elemente bezeichnet). Einer der Gründe ist, dass Typen untergeordnet werden können, und ein anderer, dass es sinnvoll ist, nur globale Elemente zu haben, die Wurzelelemente sein können.

Weitere Details zur Schemaseite finden Sie unter this article.

Nun, wie für die JAXB Frage im Besonderen. Das Problem besteht darin, dass Sie eine Klasse erstellt haben, die einem Typ entspricht, und versucht haben, sie zu serialisieren. Das bedeutet, dass JAXB sein Inhaltsmodell kennt, aber nicht wie der Elementname sein sollte. Sie benötigen RpcType zu einem Element (JAXBElement), beispielsweise zur Befestigung:

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

Die ObjectFactory wurde in das Paket gelegt erstellt von JAXB für Sie.

11

Es ist nicht offensichtlich, ich werde dir gewähren. Es kommt auf die Entscheidung Typ gegen Element an.

Wenn Sie so etwas wie

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

haben Dies ist im Wesentlichen ein „anonymer Typ“ und ist ein Typ, der nie irgendwo anders als innerhalb des Elements rpcType auftreten kann. Aufgrund dieser Gewissheit weiß XJC, dass dieser Typ immer den Namen rpcType hat, und generiert dafür eine @XmlRootElement Annotation mit dem Namen rpcType.

Auf der anderen Seite, wenn Sie

<xs:complexType name="rpcType"> 

haben dann definiert dies ein wiederverwendbares Art, die möglicherweise durch verschiedene Elemente bezeichnet werden könnte. Die Tatsache, dass in Ihrem Schema nur auf ein Element Bezug genommen wird, ist irrelevant. Aufgrund dieser Unsicherheit hecke XJC seine Wetten und generiert keine @XmlRootElement.

Die JAXB-Referenzimplementierung verfügt über ein proprietäres XJC-Flag namens "simple binding mode", das unter anderem annimmt, dass das zu kompilierende Schema niemals erweitert oder mit einem anderen kombiniert wird. Dies ermöglicht es, bestimmte Annahmen zu treffen. Wenn also ein Name complexType nur von einem element verwendet wird, generiert er oft @XmlRootElement dafür.

Die Realität ist eher subtil und komplex, aber in 90% der Fälle ist dies eine ausreichende Erklärung.

+0

Wenn bei Verwendung des 'einfachen Bindungsmodus' das xsd erweitert oder kombiniert wird und ein anderes Stammelement mit dem gleichen Typ (in der Erweiterung) definiert wird, wird ein XJC-Kompilierzeitfehler oder ein Laufzeitfehler oder unbestimmtes Verhalten auftreten ? – Vihung

1

Vorteile der genannten Typen

Der Vorteil eines Schemas global/genannten Typen ist, dass Kind/Untertypen, die den übergeordneten Typ erweitern erstellt werden kann.

<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"/> 

Das obige Fragment würde die folgende Kind Typ erstellt werden:

<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> 

Auswirkungen auf JAXB

Ein weiterer Aspekt der genannten Typen ist, dass sie durch mehrere Elemente verwendet werden können, :

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

Dies bedeutet t Der Schema-zu-Java-Compiler kann nicht einfach eines der möglichen Elemente als @XmlRootElement für die Klasse auswählen, die "rpcType" entspricht.