XSD中复杂的元素序列规则

时间:2009-06-26 09:18:36

标签: xml xsd

在我的XML中,我有6个元素X1,X2,X3,X4,X5和X6。规则如下 -

X1必须跟随X2

X2必须跟随X3

X3必须跟随X4

X4必须后跟X2,X3,X4或X5

X5必须跟随X6

X6后面可以跟X2,X3,X4,X5或X6

我正在尝试为此定义XSD。可能吗?我尝试了几个使用sequence和minOccur和maxOccur但没有工作的东西。我可以尝试任何想法吗?

2 个答案:

答案 0 :(得分:4)

XML Schema 1.0无法处理这种情况。 另一方面,Schematron直接转换您的约束,请参阅下面的工作/测试Schematron架构:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <pattern>
    <rule context="X1">
      <assert test="following-sibling::*[1][self::X2]">
        X1 must be followed by X2
      </assert>
    </rule>
    <rule context="X2">
      <assert test="following-sibling::*[1][self::X3]">
        X2 must be followed by X3
      </assert>
    </rule>
    <rule context="X3">
      <assert test="following-sibling::*[1][self::X4]">
        X3 must be followed by X4
      </assert>
    </rule>
    <rule context="X4">
      <assert test="following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5]">
        X4 must be followed by X2, X3, X4 or X5
      </assert>
    </rule>
    <rule context="X5">
      <assert test="following-sibling::*[1][self::X6]">
        X5 must be followed by X6
      </assert>
    </rule>
    <rule context="X6">
      <assert test="not(following-sibling::*) or following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5 or self::X6]">
        X6 can be followed by X2, X3, X4, X5 or X6
      </assert>
    </rule>
  </pattern>
</schema>

XML Schema 1.1将添加断言支持,但是对断言XPath适用的范围有一些限制 - 您需要将断言放在X1..X6的父元素上。

另请注意,Schematron规则可以保留在xs:annotation / xs:appinfo中的XML Schema中,您应该能够针对XML Schema和嵌入式Schematron规则进行验证。

OP评论后的跟进

下面是嵌入上述Schematron规则的XML Schema。这是一个定义元素测试的示例,可以包含X1..X6。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:sch="http://purl.oclc.org/dsdl/schematron">
  <xs:annotation>
    <xs:appinfo>
      <sch:title>Sample embedded Schematron rules</sch:title>
    </xs:appinfo>
  </xs:annotation>
  <xs:element name="test">
    <xs:annotation>
      <xs:appinfo>
        <sch:pattern>
          <sch:rule context="X1">
            <sch:assert test="following-sibling::*[1][self::X2]"> X1 must be followed by X2 </sch:assert>
          </sch:rule>
          <sch:rule context="X2">
            <sch:assert test="following-sibling::*[1][self::X3]"> X2 must be followed by X3 </sch:assert>
          </sch:rule>
          <sch:rule context="X3">
            <sch:assert test="following-sibling::*[1][self::X4]"> X3 must be followed by X4 </sch:assert>
          </sch:rule>
          <sch:rule context="X4">
            <sch:assert test="following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5]"> X4
              must be followed by X2, X3, X4 or X5 </sch:assert>
          </sch:rule>
          <sch:rule context="X5">
            <sch:assert test="following-sibling::*[1][self::X6]"> X5 must be followed by X6 </sch:assert>
          </sch:rule>
          <sch:rule context="X6">
            <sch:assert
              test="not(following-sibling::*) or following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5 or self::X6]"
              > X6 can be followed by X2, X3, X4, X5 or X6 </sch:assert>
          </sch:rule>
        </sch:pattern>
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element ref="X1"/>
        <xs:element ref="X2"/>
        <xs:element ref="X3"/>
        <xs:element ref="X4"/>
        <xs:element ref="X5"/>
        <xs:element ref="X6"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name="X1"/>
  <xs:element name="X2"/>
  <xs:element name="X3"/>
  <xs:element name="X4"/>
  <xs:element name="X5"/>
  <xs:element name="X6"/>
</xs:schema>

实例文档如下所示:

<?oxygen SCHSchema="test.xsd"?>
<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="test.xsd">
  <X1/>
  <X2/>
  <X3/>
  <X4/>
  <X4/>
  <X3/>
  <X4/>
  <X5/>
  <X6/>
  <X4/>
  <X5/>
  <X6/>
</test>

以上是使用oXygen XML Editor测试的。该实例还将XML Schema与处理指令相关联,以告知oXygen该架构包含嵌入的Schematron规则。验证是针对XML Schema和Schematron规则执行的。

答案 1 :(得分:1)

无论如何,这是一个解决方案,假设X6可以作为终端项,“OverallSequence”是基本元素。


<xs:complexType name="OverallSequence">
  <xs:group  ref="firstItem" />
</xs:complexType>

<xs:group name="sixthChoice"> <xs:choice> <xs:group ref="secondItem" /> <xs:group ref="thirdItem" /> <xs:group ref="fourthItem" /> <xs:group ref="fifthItem" /> <xs:group ref="sixthItem" /> </xs:choice> </xs:group>

<xs:group name="sixthItem"> <xs:sequence> <xs:element name="X6" type="xs:string" /> <xs:group ref="sixthChoice" minOccurs="0" > </xs:sequence> </xs:group>

<xs:group name="fifthItem"> <xs:sequence> <xs:element name="X5" type="xs:string" /> <xs:group ref="sixthItem" /> </xs:sequence> </xs:group>

<xs:group name="fourthChoice"> <xs:choice> <xs:group ref="secondItem" /> <xs:group ref="thirdItem" /> <xs:group ref="fourthItem" /> </xs:choice> </xs:group>

<xs:group name="fourthItem" /> <xs:sequence> <xs:element name="X4" type="xs:string" /> <xs:group ref="fourthChoice" minOccurs="0" > <xs:group ref="fifthItem" /> </xs:sequence> </xs:group>

<xs:group name="thirdItem" /> <xs:sequence> <xs:element name="X3" type="xs:string" /> <xs:group ref="fourthItem"> </xs:sequence> </xs:group>

<xs:group name="secondItem" /> <xs:sequence> <xs:element name="X2" type="xs:string" /> <xs:group ref="thirdItem"> </xs:sequence> </xs:group>

<xs:group name="firstItem" /> <xs:sequence> <xs:element name="X1" type="xs:string" /> <xs:group ref="secondItem"> </xs:sequence> </xs:group>