我正在尝试定义一个XSD来反映某种XML的结构。以下是此类XML的示例:
<input id="x">
<value id="x1">
<input id="y">
<value id="y1"/>
<value id="y2"/>
</input>
</value>
<value id="x2">
<input id="y">
<value id="y3"/>
<value id="y4"/>
<value id="y5"/>
</input>
<input id="z">
<value id="z1"/>
<value id="z2"/>
</input>
</value>
</input>
这表示以下内容:
input
都是一个组合框,其中包含一系列条目(value
s)。value
都是组合框中的条目。如果里面有input
s,则表示在相应的组合框中选择此值时,应显示这些输入。所以上面的例子意味着:
可以有任意嵌套,也就是说,任何value
都可以包含更多input
s,其中可能包含更多value
s等。这一切都很好而且清晰。我的问题是我想定义一个unique
限制,以保证无法指定同时显示相同id
的多个输入的情况。也就是说,input
不能拥有与id
具有相同input
的任何祖先。例如:
<input id="x"> <!-- illegal -->
<value id="x1">
<input id="x"> <!-- illegal -->
<value id="y1"/>
<value id="y2"/>
</input>
</value>
...
</input>
这是非法的,因为在另一个输入 x
中有输入 x<input id="x"> <!-- illegal -->
<value id="x1">
<input id="y">
<value id="y1">
<input id="x"> <!-- illegal -->
<value id="z1"/>
<value id="z2"/>
</input>
</value>
<value id="y2"/>
</input>
</value>
...
</input>
由于同样的原因,这是非法的。层次结构中两个 x 输入之间有多少个节点无关紧要;这是不允许的。
但是,这是合法的:
<input id="x">
<value id="x1">
<input id="y"> <!-- legal -->
<value id="y1"/>
<value id="y2"/>
</input>
</value>
<value id="x2">
<input id="y"> <!-- legal -->
<value id="y3"/>
<value id="y4"/>
<value id="y5"/>
</input>
<input id="z">
<value id="z1"/>
<value id="z2"/>
</input>
</value>
</input>
两个 y 输入位于不同的层次结构中,因此没有冲突。
我很难找到要在unique
限制中使用的XPath表达式:这似乎是我正在寻找的......
<xs:unique name="uniqueInputIdInBranch">
<xs:selector xpath="ancestor-or-self::input"/>
<xs:field xpath="@id"/>
</xs:unique>
...但是在XSD中似乎不允许使用这种XPath。我明白了:
表达式'ancestor-or-self :: input'对于XML Schema支持的XPath子集无效。
Afaict我的选择器应该在祖先层次结构中向上而不是向下......
<xs:unique name="uniqueInputIdInBranch">
<xs:selector xpath=".//input"/>
<xs:field xpath="@id"/>
</xs:unique>
...因为向下将不会区分“分支”并将其报告为无效,即使两个 y 输入位于不同的分支中:
<input id="x">
<value id="x1">
<input id="y"> <!-- legal but marked as illegal -->
<value id="y1"/>
<value id="y2"/>
</input>
</value>
<value id="x2">
<input id="y"> <!-- legal but marked as illegal -->
<value id="y3"/>
<value id="y4"/>
<value id="y5"/>
</input>
<input id="z">
<value id="z1"/>
<value id="z2"/>
</input>
</value>
</input>
有没有办法实现上面描述的“独特的分支内”验证?到目前为止,这是XSD,如果你想玩它:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="test"
xmlns:tns="test"
elementFormDefault="qualified">
<xs:element name="inputs" type="tns:inputsType"/>
<xs:complexType name="inputsType">
<xs:sequence>
<xs:element name="input" type="tns:inputType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="inputType">
<xs:sequence>
<xs:element name="value" type="tns:valueType" minOccurs="1" maxOccurs="unbounded">
<xs:unique name="uniqueInputIdInBranch">
<xs:selector xpath="ancestor-or-self::input"/>
<xs:field xpath="@id"/>
</xs:unique>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:token" use="required"/>
</xs:complexType>
<xs:complexType name="valueType">
<xs:sequence>
<xs:element name="input" type="tns:inputType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="id" type="xs:token" use="required"/>
</xs:complexType>
</xs:schema>
对不起,很长的帖子,谢谢!