使元素值独特

时间:2014-05-18 05:27:38

标签: xml xsd

我正在做一个小型的XML项目,我正在定义一个用XML制作的国际象棋游戏状态的模式。这包括创建棋子元素并为这些片段创建子元素,这些元素引用它们在PGN中的位置(位置游戏符号)。

该文件继续定义国王,女王等及其职位。我如何确保位置标签内的值是唯一的,即一个棋子在17处不能有两个位置,因为在棋盘的同一个方格上有两个位置。

<position>17</position>
<position>17</position>

我尝试使用一个独特的约束,但它在片段元素中有多个位置元素时吓坏了。我如何制作这些作品的价值总是独一无二的,没有两件可以共享相同的位置值?

编辑: 因此,唯一约束的位置适用于同一块标记内的位置元素,但是有一种方法可以在整个文档中的任何位置执行此操作。例如:

<board-side name="white">
    <pieces>
        <piece name="Pawn" symbol="p">
            <position>12</position>

<board-side name="BLACK">
    <pieces>
        <piece name="Pawn" symbol="P">
            <position>17</position>

上述两个XML片段都在他们自己的板边标签内。是否有办法使它如果我将BLACK板的位置更改为12,它将抛出一个唯一的约束错误,或者唯一的只适用于同一个标签中的多个元素?

编辑2:整体架构

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema id="chess_schema" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:simpleType name="ident">
        <xs:restriction base="xs:string">
            <xs:enumeration value="P" />
            <xs:enumeration value="p" />
            <xs:enumeration value="Q" />
            <xs:enumeration value="q" />
            <xs:enumeration value="R" />
            <xs:enumeration value="r" />
            <xs:enumeration value="N" />
            <xs:enumeration value="n" />
            <xs:enumeration value="B" />
            <xs:enumeration value="b" />
            <xs:enumeration value="K" />
            <xs:enumeration value="k" />
        </xs:restriction>
    </xs:simpleType>

    <xs:element name="game-state">
        <xs:complexType>
            <xs:sequence>

                <xs:element name="board-state">
                    <xs:complexType>
                        <xs:sequence>

                            <xs:element name="board-side" minOccurs="2" maxOccurs="2">
                                <xs:complexType>
                                    <xs:sequence>

                                        <xs:element name="pieces">
                                            <xs:complexType>
                                                <xs:sequence>

                                                    <xs:element name="piece" maxOccurs="6">
                                                        <xs:complexType>
                                                            <xs:sequence>

                                                                <xs:element name="position" minOccurs="0" maxOccurs="8" >
                                                                    <xs:simpleType>
                                                                        <xs:restriction base="xs:int">
                                                                            <xs:minInclusive value="11" />
                                                                            <xs:maxInclusive value="88" />
                                                                        </xs:restriction>
                                                                    </xs:simpleType>
                                                                </xs:element>

                                                            </xs:sequence>
                                                            <xs:attribute name="symbol" type="ident" />
                                                            <xs:attribute name="name" type="xs:string" />
                                                        </xs:complexType>
                                                    </xs:element>

                                                </xs:sequence>
                                            </xs:complexType>
                                        </xs:element>

                                        <xs:element name="taken-pieces" maxOccurs="1" minOccurs="0" type="xs:string" />

                                    </xs:sequence>
                                    <xs:attribute name="name" type="xs:string" />
                                </xs:complexType>
                            </xs:element>

                        </xs:sequence>
                    </xs:complexType>
                </xs:element>

            </xs:sequence>
        </xs:complexType>

        <xs:unique name="uniquePos">
            <xs:selector xpath="board-side/pieces/piece/position" />
            <xs:field xpath="." />
        </xs:unique>

    </xs:element> <!--end game-state root-->
</xs:schema>

1 个答案:

答案 0 :(得分:2)

唯一性约束可确保您的位置元素在指定的范围中是唯一的。

您应该在表示该范围的元素中定义约束。例如,如果范围是piece元素,则可以通过相对于此上下文的XPath选择器将其与position元素相关联。

如果你有没有目标命名空间,你可以简单地使用它而不用前缀:

<xs:element name="piece">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="position" minOccurs="0" maxOccurs="8"/>
        </xs:sequence>
    </xs:complexType>
    <xs:unique name="uniquePos">
        <xs:selector xpath="position" />
        <xs:field xpath="." />
    </xs:unique>
</xs:element>

但是,如果您的模式具有目标命名空间,则必须使用前缀声明它,因为XPath假定未加前缀的名称属于no-namespace。所以你需要这样的东西:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified"
           xmlns="ns1" xmlns:chess="ns1" targetNamespace="ns1">  ...

(你真的不需要将它复制为默认命名空间,除非你在其他地方也引用了不合格的类型,但是你需要带前缀的类型。)

然后您可以为XPath选择器添加前缀:

<xs:unique name="uniquePos">
    <xs:selector xpath="chess:position" />
    <xs:field xpath="." />
</xs:unique>

更新考虑您的版本。

如果要增加唯一性约束有效的范围,只需将声明放在该范围内即可。例如,如果您希望这些职位在整个game-state元素中是唯一的,您可以在那里声明:

<xs:element name="game-state">
    ...
    <xs:unique name="uniquePos">
        <xs:selector xpath="/board-state/board-side/pieces/piece/position" />
        <xs:field xpath="." />
    </xs:unique>
</xs:element>

如果在position以下的任何上下文中有两个game-state元素具有相同的值,则会导致验证错误。只要XPath表达式在该上下文中有效,您也可以将其放在其他位置。例如,在board-state中,它将是:

<xs:element name="board-state">
    ...
    <xs:unique name="uniquePos">
        <xs:selector xpath="board-side/pieces/piece/position" />
        <xs:field xpath="." />
    </xs:unique>
</xs:element>