XSD 独特的元素和属性
XSD unique elements and attributes
大家好!这是我关于 Whosebug 的第一个问题,虽然我经常阅读这个网站上的帖子。
直截了当,我正在尝试定义一个 XML 架构,如下所示:
<xs:element name="keyConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="move">
<xs:complexType>
<xs:attribute name="N" type="keyCode"/>
<xs:attribute name="NE" type="keyCode"/>
<xs:attribute name="E" type="keyCode"/>
<xs:attribute name="SE" type="keyCode"/>
<xs:attribute name="S" type="keyCode"/>
<xs:attribute name="SW" type="keyCode"/>
<xs:attribute name="W" type="keyCode"/>
<xs:attribute name="NW" type="keyCode"/>
</xs:complexType>
</xs:element>
<xs:element name="wait" type="keyCode"/>
<xs:element name="select" type="keyCode"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="."/>
<xs:field xpath="move/@*"/>
<xs:field xpath="wait"/>
<xs:field xpath="select"/>
</xs:unique>
keyCode
是一种用于识别键盘按下的枚举类型,它接受 xs:int
的子集。
我的想法是,我不想验证将多个可能的操作映射到同一键的 XML 文件,因此以下 XML 应该是无效的:
<keyConfiguration>
<move N="101" NE="101" E="102" SE="99" S="98" SW="97" W="100" NW="103"/>
<wait>101</wait>
<select>101</select>
</keyConfiguration>
向北、东北等移动的属性和 wait/select 动作的元素都重复了,none 应该会发生。移动方向的所有属性和其他操作的所有元素都应该是唯一的。
遗憾的是,当我尝试根据 XSD 验证给定的 XML 时,它是有效的!我认为 unique 标记中的 XPath 已损坏,但我不知道如何解决此问题(我尝试了多种变体,包括 <xs:field xpath="*/move/@*"/>
和 <xs:field xpath="*/wait"/>
,但仍然无效)。
提前致谢!
编辑:这里是完整的架构定义,如果有帮助的话:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="keyCode">
<xs:restriction base="xs:int">
<xs:enumeration value="10"/> <!-- Enter -->
...
<xs:enumeration value="96"/> <!-- NumPad-0 -->
<xs:enumeration value="97"/> <!-- NumPad-1 -->
<xs:enumeration value="98"/> <!-- NumPad-2 -->
<xs:enumeration value="99"/> <!-- NumPad-3 -->
<xs:enumeration value="100"/> <!-- NumPad-4 -->
<xs:enumeration value="101"/> <!-- NumPad-5 -->
<xs:enumeration value="102"/> <!-- NumPad-6 -->
<xs:enumeration value="103"/> <!-- NumPad-7 -->
<xs:enumeration value="104"/> <!-- NumPad-8 -->
<xs:enumeration value="105"/> <!-- NumPad-9 -->
...
</xs:restriction>
</xs:simpleType>
<xs:element name="keyConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="move">
<xs:complexType>
<xs:attribute name="N" type="keyCode"/>
<xs:attribute name="NE" type="keyCode"/>
<xs:attribute name="E" type="keyCode"/>
<xs:attribute name="SE" type="keyCode"/>
<xs:attribute name="S" type="keyCode"/>
<xs:attribute name="SW" type="keyCode"/>
<xs:attribute name="W" type="keyCode"/>
<xs:attribute name="NW" type="keyCode"/>
</xs:complexType>
</xs:element>
<xs:element name="wait" type="keyCode"/>
<xs:element name="select" type="keyCode"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="."/>
<xs:field xpath="*/move/@*"/>
<xs:field xpath="*/wait"/>
<xs:field xpath="*/select"/>
</xs:unique>
</xs:element>
</xs:schema>
可能跟命名空间有关?我试着在网上寻找 xpath 示例,但我找不到任何可以帮助我确定问题的东西。谢谢!
我认为使用 XSD 1.0 无法做到这一点。 Unique 以这种方式工作:xs:selector selects 一组元素,fields 值应该是唯一的。
因此,在 select 或者你应该 select 每个 属性中, 的值和 的值,以及字段中那些节点的值(点字符“.”)。请记住,在 XPath 中,运算符 | 给出 node-sets 之间的并集。理想情况下,您可以使用它来解决您的问题:
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="move/@* | wait | select"/>
<xs:field xpath="."/>
</xs:unique>
但是 XSD 不允许在 xs:selector 中使用 select 属性。但我希望你明白,如果 N、NE、W 等是元素而不是属性,你被允许使用类似下面的东西并且它会起作用:
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="move/* | wait | select"/>
<xs:field xpath="."/>
</xs:unique>
这会起作用,因为您只 selecting xs:selector 中的元素。
使用 XSD 1.1 这可以使用 xs:assert 来完成,它允许您使用 xpath(selector、field、unique 等只允许您使用受限的 XPath子集)。将解决此问题的示例断言:
<xs:assert test="count(distinct-values(move/@* | wait | select)) = count(move/@* | wait | select)"/>
此外请记住,使用范围(从 10 到 105)和使用联合(从 10 到 50 + 从 60 到 105)比使用 xs:enumeration 更容易定义 keyCode 类型。
连续值示例:
<xs:simpleType name="keyCode">
<xs:restriction base="xs:int">
<xs:minInclusive value="10"/>
<xs:maxInclusive value="105"/>
</xs:restriction>
</xs:simpleType>
非连续值示例:
<xs:simpleType name="keyCode">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="10"/>
<xs:maxInclusive value="50"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="60"/>
<xs:maxInclusive value="105"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
大家好!这是我关于 Whosebug 的第一个问题,虽然我经常阅读这个网站上的帖子。
直截了当,我正在尝试定义一个 XML 架构,如下所示:
<xs:element name="keyConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="move">
<xs:complexType>
<xs:attribute name="N" type="keyCode"/>
<xs:attribute name="NE" type="keyCode"/>
<xs:attribute name="E" type="keyCode"/>
<xs:attribute name="SE" type="keyCode"/>
<xs:attribute name="S" type="keyCode"/>
<xs:attribute name="SW" type="keyCode"/>
<xs:attribute name="W" type="keyCode"/>
<xs:attribute name="NW" type="keyCode"/>
</xs:complexType>
</xs:element>
<xs:element name="wait" type="keyCode"/>
<xs:element name="select" type="keyCode"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="."/>
<xs:field xpath="move/@*"/>
<xs:field xpath="wait"/>
<xs:field xpath="select"/>
</xs:unique>
keyCode
是一种用于识别键盘按下的枚举类型,它接受 xs:int
的子集。
我的想法是,我不想验证将多个可能的操作映射到同一键的 XML 文件,因此以下 XML 应该是无效的:
<keyConfiguration>
<move N="101" NE="101" E="102" SE="99" S="98" SW="97" W="100" NW="103"/>
<wait>101</wait>
<select>101</select>
</keyConfiguration>
向北、东北等移动的属性和 wait/select 动作的元素都重复了,none 应该会发生。移动方向的所有属性和其他操作的所有元素都应该是唯一的。
遗憾的是,当我尝试根据 XSD 验证给定的 XML 时,它是有效的!我认为 unique 标记中的 XPath 已损坏,但我不知道如何解决此问题(我尝试了多种变体,包括 <xs:field xpath="*/move/@*"/>
和 <xs:field xpath="*/wait"/>
,但仍然无效)。
提前致谢!
编辑:这里是完整的架构定义,如果有帮助的话:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="keyCode">
<xs:restriction base="xs:int">
<xs:enumeration value="10"/> <!-- Enter -->
...
<xs:enumeration value="96"/> <!-- NumPad-0 -->
<xs:enumeration value="97"/> <!-- NumPad-1 -->
<xs:enumeration value="98"/> <!-- NumPad-2 -->
<xs:enumeration value="99"/> <!-- NumPad-3 -->
<xs:enumeration value="100"/> <!-- NumPad-4 -->
<xs:enumeration value="101"/> <!-- NumPad-5 -->
<xs:enumeration value="102"/> <!-- NumPad-6 -->
<xs:enumeration value="103"/> <!-- NumPad-7 -->
<xs:enumeration value="104"/> <!-- NumPad-8 -->
<xs:enumeration value="105"/> <!-- NumPad-9 -->
...
</xs:restriction>
</xs:simpleType>
<xs:element name="keyConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="move">
<xs:complexType>
<xs:attribute name="N" type="keyCode"/>
<xs:attribute name="NE" type="keyCode"/>
<xs:attribute name="E" type="keyCode"/>
<xs:attribute name="SE" type="keyCode"/>
<xs:attribute name="S" type="keyCode"/>
<xs:attribute name="SW" type="keyCode"/>
<xs:attribute name="W" type="keyCode"/>
<xs:attribute name="NW" type="keyCode"/>
</xs:complexType>
</xs:element>
<xs:element name="wait" type="keyCode"/>
<xs:element name="select" type="keyCode"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="."/>
<xs:field xpath="*/move/@*"/>
<xs:field xpath="*/wait"/>
<xs:field xpath="*/select"/>
</xs:unique>
</xs:element>
</xs:schema>
可能跟命名空间有关?我试着在网上寻找 xpath 示例,但我找不到任何可以帮助我确定问题的东西。谢谢!
我认为使用 XSD 1.0 无法做到这一点。 Unique 以这种方式工作:xs:selector selects 一组元素,fields 值应该是唯一的。
因此,在 select 或者你应该 select 每个 属性中, 的值和 的值,以及字段中那些节点的值(点字符“.”)。请记住,在 XPath 中,运算符 | 给出 node-sets 之间的并集。理想情况下,您可以使用它来解决您的问题:
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="move/@* | wait | select"/>
<xs:field xpath="."/>
</xs:unique>
但是 XSD 不允许在 xs:selector 中使用 select 属性。但我希望你明白,如果 N、NE、W 等是元素而不是属性,你被允许使用类似下面的东西并且它会起作用:
<xs:unique name="uniqueKeyCode">
<xs:selector xpath="move/* | wait | select"/>
<xs:field xpath="."/>
</xs:unique>
这会起作用,因为您只 selecting xs:selector 中的元素。
使用 XSD 1.1 这可以使用 xs:assert 来完成,它允许您使用 xpath(selector、field、unique 等只允许您使用受限的 XPath子集)。将解决此问题的示例断言:
<xs:assert test="count(distinct-values(move/@* | wait | select)) = count(move/@* | wait | select)"/>
此外请记住,使用范围(从 10 到 105)和使用联合(从 10 到 50 + 从 60 到 105)比使用 xs:enumeration 更容易定义 keyCode 类型。
连续值示例:
<xs:simpleType name="keyCode">
<xs:restriction base="xs:int">
<xs:minInclusive value="10"/>
<xs:maxInclusive value="105"/>
</xs:restriction>
</xs:simpleType>
非连续值示例:
<xs:simpleType name="keyCode">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="10"/>
<xs:maxInclusive value="50"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="60"/>
<xs:maxInclusive value="105"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>