此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"/>
是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>
理由是在#1中尝试编组bean时(在jaxb2中)我得到了异常:
[com.sun.istack.SAXException2: unable to marshal type "netconf.RpcType" as an element because it is missing an @XmlRootElement annotation]
我一遍又一遍地阅读this文章,并且真的无法掌握差异,为什么它会是#1 vs#2 ...
答案 0 :(得分:12)
这不明显,我会给你的。它归结为类型与元素决策。
当你有类似
的东西时<xs:element name="rpcType">
<xs:complexType>
这实际上是一个“匿名类型”,并且是一种在元素rpcType
内部以外的任何地方都不会出现的类型。由于这种确定性,XJC知道该类型将始终具有名称rpcType
,因此为其生成@XmlRootElement
注释,并使用rpcType
名称。
另一方面,当你有
时<xs:complexType name="rpcType">
然后,这定义了一个可重用的类型,可能由几个不同的元素引用。在您的模式中它只由一个元素引用的事实是无关紧要的。由于不确定性,XJC对冲其赌注并且不生成@XmlRootElement
。
JAXB Reference Implementation有一个名为"simple binding mode"的专有XJC标志,除其他外,它假定您编译的模式永远不会扩展或与另一个模式组合。这允许它做出某些假设,因此如果它看到一个complexType
只被一个element
使用,那么它通常会为它生成@XmlRootElement
。
现实比这更微妙和复杂,但在90%的情况下,这是一个充分的解释。
答案 1 :(得分:1)
相当棘手的问题。使用类型而不是元素设计模式有很多原因(这种方法被称为“百叶窗”方法而不是“萨拉米片”用于使用全局元素)。其中一个原因是类型可以是子类型,另一个原因是只有全局元素才可以是根元素。
有关架构方面的更多详细信息,请参阅this article。
现在,尤其是JAXB问题。问题是您创建了一个与类型对应的类并尝试将其序列化。这意味着JAXB知道其内容模型,但不知道元素名称应该是什么。您需要将RpcType附加到元素(JAXBElement),例如:
marshaller.marshal(new ObjectFactory().createRpc(myRpcType));
ObjectFactory
已放入JAXB为您创建的包中。
答案 2 :(得分:1)
命名类型的优点
使用全局/命名类型的模式的优点是可以创建扩展父类型的子/子类型。
<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"/>
上面的片段将允许创建以下子类型:
<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>
对JAXB的影响
命名类型的另一个方面是它们可能被多个元素使用:
<xs:element name="FOO" type="rpcType"/>
<xs:element name="BAR" type="rpcType"/>
这意味着Java编译器的模式不能简单地选择一个可能的元素作为对应于“rpcType”的类的@XmlRootElement。