Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSD Formatting <element><complexType> vs <complexType/><element/>

Tags:

jaxb

xsd

This XSD portion was obtained from: http://www.iana.org/assignments/xml-registry/schema/netconf.xsd

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

And is the core to function calls in NETCONF being the node of an XML document. I am curious as to why it is not something like:

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

The reasoning is that in #1 when trying to marshall a bean (in jaxb2) I get the exception:

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

I have been reading this article over and over again, and really cant get a hold of the difference, and why it would be #1 vs #2...

like image 356
wuntee Avatar asked Sep 03 '10 20:09

wuntee


People also ask

What is complexType in XSD?

The complexType element defines a complex type. A complex type element is an XML element that contains other elements and/or attributes.

What is simple type and complexType in XSD?

XSD elements can be of type simpleType , complexType , or anyType . An element of type simpleType contains only text. It cannot have attributes and elements. An element of type complexType can contain text, elements, and attributes.

What is the difference between element and attribute in XSD?

An attribute provides extra information within an element. Attributes are defined within an XSD as follows, having name and type properties. An Attribute can appear 0 or 1 times within a given element in the XML document. Attributes are either optional or mandatory (by default the are optional).


2 Answers

It's not obvious, I'll grant you. It comes down to the type vs element decision.

When you have something like

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

This is essentially an "anonymous type", and is a type which can never occur anywhere other than inside the element rpcType. Because of this certainty, XJC knows that that type will always have the name rpcType, and so generates an @XmlRootElement annotation for it, with the rpcType name.

On the other hand, when you have

<xs:complexType name="rpcType">

then this defines a re-usable type which could potentially be referred to by several different elements. The fact that in your schema it is only referred to by one element is irrelevant. Because of this uncertainty, XJC hedges its bets and does not generate an @XmlRootElement.

The JAXB Reference Implementation has a proprietary XJC flag called "simple binding mode" which, among other things, assumes that the schema you're compiling will never be extended or combined with another. This allows it to make certain assumptions, so if it sees a named complexType only being used by one element, then it will often generate @XmlRootElement for it.

The reality is rather more subtle and complex than that, but in 90% of cases, this is a sufficient explanation.

like image 77
skaffman Avatar answered Jan 02 '23 20:01

skaffman


Quite an involved question. There are many reasons to design schemas using types rather than elements (this approach is called the "venetian blind" approach versus "salami slice" for using global elements). One of the reasons is that types can be sub-typed, and another that it may be useful to only have elements global that can be root elements.

See this article for some more details on the schema side.

Now, as for the JAXB question in particular. The problem is that you created a class corresponding to a type and tried to serialise it. That means JAXB knows its content model, but not what the element name should be. You need to attach your RpcType to an element (JAXBElement), for example:

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

The ObjectFactory was placed into the package created by JAXB for you.

like image 38
xcut Avatar answered Jan 02 '23 21:01

xcut