在我的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但没有工作的东西。我可以尝试任何想法吗?
答案 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规则进行验证。
下面是嵌入上述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>