XSD Formatting vs

2020-06-18 06:03发布

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

标签: xsd jaxb
3条回答
够拽才男人
2楼-- · 2020-06-18 06:34

Advantages of Named Types

The advantage of a schema using global/named types is that child/sub types can be created that extend the parent type.

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

The above fragment would allow the following child type to be created:

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

Impact on JAXB

Another aspect of named types is that they may be used by multiple elements:

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

This means that the schema to Java compiler cannot simply just pick one of the possible elements to be the @XmlRootElement for the class corresponding to "rpcType".

查看更多
一纸荒年 Trace。
3楼-- · 2020-06-18 06:42

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.

查看更多
4楼-- · 2020-06-18 06:46

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.

查看更多
登录 后发表回答