如何在XML Schema中获取元素顺序约束?

时间:2009-10-30 15:35:28

标签: xml xsd

我有一个XML Schema(xsd文件)片段,其中我希望NAMEADRESS元素以任何顺序出现,但始终在FILM序列之前

所以我一直试图这样做:

  <xs:element name="ROOM">
    <xs:complexType>
      <xs:all>
        <xs:element ref="NAME"/>
        <xs:element ref="ADRESS"/>
      </xs:all>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="FILM"/>
      </xs:sequence>
      <xs:attribute name="group" type="xs:NCName"/>
      <xs:attribute name="typ" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>

我知道<xs:all>标记不能是同一子级别的其他元素的元素的一部分......但是找不到出路......

有什么建议吗?提前谢谢!

2 个答案:

答案 0 :(得分:3)

这是XSD架构的限制。我将引用:http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/然后评论:

<小时/> 存在用于约束组中元素的第三选项:组中的所有元素可以出现一次或根本不出现,并且它们可以以任何顺序出现。 all group(提供SGML&amp; -Connector的简化版本)仅限于任何内容模型的顶级。此外,组的子项必须都是单独的元素(没有组),并且内容模型中的任何元素都不会出现多次,即minOccurs和maxOccurs的允许值为0和1.例如,允许子元素为purchaseOrder以任何顺序出现,我们可以将PurchaseOrderType重新定义为: '全部'组

<xsd:complexType name="PurchaseOrderType">
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element ref="comment" minOccurs="0"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

根据这个定义,注释元素可以选择出现在purchaseOrder中,它可以出现在任何shipTo,billTo和items元素之前或之后,但它只能出现一次。此外,所有小组的规定不允许我们在小组外宣布诸如评论之类的元素作为使其不止一次出现的手段。 XML Schema规定,所有组必须作为内容模型顶部的唯一子项出现。换句话说,以下是非法的: 带有“全部”组的非法示例

<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:sequence>
   <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

我对当时讨论的回忆是,xsd:all如果不受此限制,那么模型就太复杂了。它很快扩展到非确定性解析模型。所以限制是0或1,没有兄弟姐妹。

SGML使用&连接器有一个更强大的模型,但并非所有系统都使用它。

编辑如果您希望在此级别验证XML,可以使用Schematron作为架构之后的第二个验证器。它基于XSLT,这种类型的约束更容易表达。

答案 1 :(得分:1)

好吧,看起来我最终找到了办法:

  <xs:element name="ROOM">
    <xs:complexType>

      <xs:choice>
        <xs:sequence>
          <xs:element ref="NAME"/>
          <xs:element ref="ADRESS"/>
          <xs:element maxOccurs="unbounded" ref="FILM"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element ref="ADRESS"/>
          <xs:element ref="NAME"/>
          <xs:element maxOccurs="unbounded" ref="FILM"/>
        </xs:sequence>
      </xs:choice>

      <xs:attribute name="group" type="xs:NCName"/>
      <xs:attribute name="typ" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>

但我认为它没有得到很好的优化,考虑到如果你想用10个元素做这个,你必须指定所有的排列...