我想为2个不同的xml创建一个模式文件(我可以将其拆分为2个模式,但由于根元素相同,我希望将其保存在一个文件中)。
现在我有两种不同的XML。
<orderStatus shipStatus="SHIPPED/PENDING">
<orderId>1234</orderId>
<orderedBy>userName</orderedBy>
<orderedOn>2012-07-23T11:35:51.000-04:00</orderedOn>
</orderStatus>
,第二个XML是
<orderStatus modifyShipStatus="SUSPENDED/PENDING">
<shipStatus>101</shipStatus>
</orderStatus>
我怎么能为这2个xml提供1 xsd?当我尝试使用一个1类型创建根元素时,它工作正常但是当我尝试添加另一个类型时,JAXB抛出错误,该元素已经定义。这使得感觉。
答案 0 :(得分:2)
答案部分取决于您想要说什么,部分取决于您使用的模式语言:DTD? XSD 1.0? XSD 1.1? RelaxNG?其他......?哦,是的,我看到问题标记为XSD,所以我假设您正在寻找XSD解决方案。
如果您想说orderStatus
元素可以 序列orderId
,orderedBy
或orderedOn
或序列shipStatus
作为子级,并且属性shipStatus
和modifyShipStatus
是可选的,然后在内容模型中这样说是直截了当的。
在DTD表示法中(我在这里使用它的紧凑性)你会写:
<!ELEMENT orderStatus ((orderId, orderedBy, orderedOn) | shipStatus) >
<!ATTLIST orderStatus
shipStatus CDATA #IMPLIED
modifyShipStatus CDATA #IMPLIED
>
或者在XSD表示法中,写下
<xs:element name="orderStatus" type="my:orderStatus"/>
<xs:complexType name="orderStatus">
<xs:choice>
<xs:sequence>
<xs:element ref="my:orderId"/>
<xs:element ref="my:orderedBy"/>
<xs:element ref="my:orderedOn"/>
</xs:sequence>
<xs:element ref="my:shipStatus"/>
</xs:choice>
<xs:attribute name="shipStatus"/>
<xs:attribute name="modifyShipStatus"/>
</xs:complexType>
然后你就完成了。
如果您只想要允许两个属性中的一个,或者您希望合法子项依赖于是否存在一个或另一个属性,则事情会更复杂。 (有些文档设计人员会说,如果你想要的话,你有两个非常不同的元素类型,你坚持使用相同的名称进行调用,这使得验证变得非常困难。)
在这种情况下,您的选择是:
如上所述使用DTD和/或XSD 1.0架构,并在文档中或使用Schematron或其他方法表达其他约束。
使用XSD 1.1,如上所述定义内容模型和属性,并添加断言以表示
shipStatus
和modifyShipStatus
。shipStatus
的孩子出现时,必须显示属性orderId
。modifyShipStatus
的孩子出现时,必须显示属性shipStatus
。使用XSD 1.1,为两种形式的orderStatus
元素定义两种不同的类型,并使用条件类型赋值来说明适用的类型:
XSD看起来像这样:
<xs:complexType name="orderStatus1">
<xs:sequence>
<xs:element ref="my:orderId"/>
<xs:element ref="my:orderedBy"/>
<xs:element ref="my:orderedOn"/>
</xs:sequence>
<xs:attribute name="shipStatus"/>
</xs:complexType>
<xs:complexType name="orderStatus2">
<xs:element ref="my:shipStatus"/>
<xs:attribute name="modifyShipStatus"/>
</xs:complexType>
<xs:element name="orderStatus">
<xs:alternative test="@shipStatus" type="my:orderStatus1"/>
<xs:alternative test="@modifyShipStatus" type="my:orderStatus2"/>
</xs:element>