我正在做一个小型的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>
答案 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>