XSD格式化<element> <complexType> vs <complexType /> <element />

wun*_*tee 6 xsd jaxb

此XSD部分来自: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"/>
Run Code Online (Sandbox Code Playgroud)

并且是NETCONF中函数调用的核心是XML文档的节点.我很好奇为什么它不是这样的:

 <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>
Run Code Online (Sandbox Code Playgroud)

理由是在#1中尝试编组bean时(在jaxb2中)我得到了异常:

[com.sun.istack.SAXException2: unable to marshal type "netconf.RpcType" as an element because it is missing an @XmlRootElement annotation]
Run Code Online (Sandbox Code Playgroud)

我一遍又一遍地阅读这篇文章,真的无法掌握差异,为什么它会#1对#2 ...

ska*_*man 12

这不明显,我会给你的.它归结为类型与元素决策.

当你有类似的东西

<xs:element name="rpcType">
   <xs:complexType>
Run Code Online (Sandbox Code Playgroud)

这本质上是一个"匿名类型",并且是一种在元素内部以外的任何地方都不会出现的类型rpcType.由于这种确定性,XJC知道该类型将始终具有名称rpcType,因此@XmlRootElement为其生成带有rpcType名称的注释.

另一方面,当你有

<xs:complexType name="rpcType">
Run Code Online (Sandbox Code Playgroud)

然后,这定义了一个可重用的类型,可能由几个不同的元素引用.在您的模式中它只由一个元素引用的事实是无关紧要的.由于这种不确定性,XJC对冲其赌注并且不产生@XmlRootElement.

JAXB参考实现有一个称为"简单绑定模式"的专有XJC标志,除其他外,它假定您编译的模式永远不会扩展或与另一个模式组合.这允许它做出某些假设,因此如果它看到一个名字complexType只被一个人使用element,那么它通常会@XmlRootElement为它生成.

现实比这更微妙和复杂,但在90%的情况下,这是一个充分的解释.


xcu*_*cut 1

这是一个相当复杂的问题。使用类型而不是元素来设计模式的原因有很多(这种方法称为“百叶窗”方法,相对于使用全局元素的“萨拉米切片”方法)。原因之一是类型可以进行子类型化,另一个原因是只有可以作为根元素的全局元素可能很有用。

有关架构方面的更多详细信息,请参阅本文。

现在,特别是关于 JAXB 问题。问题是您创建了一个与某个类型相对应的类并尝试序列化它。这意味着 JAXB 知道其内容模型,但不知道元素名称应该是什么。您需要将 RpcType 附加到元素 (JAXBElement),例如:

marshaller.marshal(new ObjectFactory().createRpc(myRpcType));
Run Code Online (Sandbox Code Playgroud)

它ObjectFactory已放入 JAXB 为您创建的包中。