选择节点

时间:2018-02-07 12:35:23

标签: xml xpath xsd

我正在尝试定义一个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,则表示在相应的组合框中选择此值时,应显示这些输入。

所以上面的例子意味着:

  • 有一个组合框 x ,其中包含条目 x1 x2
  • 如果选择 x1
    • 显示组合框 y ,其中包含条目 y1 y2
  • 如果选择 x2
    • 显示组合框 y ,其中包含条目 y3 y4 y5
    • 显示组合框 z ,其中包含条目 z1 z2

可以有任意嵌套,也就是说,任何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>

对不起,很长的帖子,谢谢!

0 个答案:

没有答案