0

我想为 2 个不同的 xml 创建一个架构文件(我可以将其拆分为 2 个架构,但由于根元素相同,我想将其保存在一个文件中)。

现在我有 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 会抛出该元素已定义的错误。这是有道理的。

4

1 回答 1

2

答案部分取决于您到底想说什么,部分取决于您使用的模式语言:DTD?XSD 1.0?XSD 1.1?放松?其他 ...?哦,对了,我看到问题被标记为 XSD,所以我假设您正在寻找 XSD 解决方案。

如果你想说一个orderStatus元素可以有序列、、或序列作为子元素,并且属性和是可选的,那么在内容模型中这样说很简单。orderIdorderedByorderedOn shipStatusshipStatusmodifyShipStatus

在 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,如上所述定义内容模型和属性,并添加断言来表示

    • 正是属性之一shipStatusmodifyShipStatus必须出现。
    • 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>
  • 我会顺便指出,它的爱好者经常引用 Relax NG 制定此类约束的能力作为其优势之一。
于 2012-08-16T20:30:22.490 回答