【问题标题】:XSD unique elements and attributesXSD 独特的元素和属性
【发布时间】:2015-12-30 16:02:11
【问题描述】:

大家!这是我关于 stackoverflow 的第一个问题,虽然我经常阅读这个网站上的帖子。

为了切入正题,我正在尝试定义一个如下所示的 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>

移动到北方、东北等的两个属性和等待/选择操作的元素都重复了,应该不会发生。移动方向的所有属性和其他动作的所有元素都应该是唯一的。

遗憾的是,当我尝试根据 XSD 验证给定的 XML 时,它是有效的!我认为唯一标记中的 XPath 已损坏,但我不知道如何解决此问题(我尝试了多种变体,包括 &lt;xs:field xpath="*/move/@*"/&gt;&lt;xs:field xpath="*/wait"/&gt;,但仍然无法正常工作)。

提前致谢!

编辑:这里是完整的架构定义,如果有帮助的话:

<?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 示例,但找不到任何可以帮助我识别问题的东西。谢谢!

【问题讨论】:

    标签: xml xpath xsd


    【解决方案1】:

    我认为这不能使用 XSD 1.0 完成。 Unique 以这种方式工作:xs:selector 选择一组元素,其中 fields 的值应该是唯一的。

    因此,在选择器中,您应该选择每个 属性、 的值和 的值,并在字段中选择那些节点(点字符“.”)。请记住,在 XPath 中,运算符 | 给出了节点集之间的联合。理想情况下,您可以使用它来解决您的问题:

    <xs:unique name="uniqueKeyCode">
        <xs:selector xpath="move/@* | wait | select"/>
        <xs:field xpath="."/>
    </xs:unique>
    

    但是XSD 不允许选择xs:selector 中的属性。但我希望你明白,如果 NNEW 等是元素而不是属性,你可以使用类似以下的内容和它会起作用的:

    <xs:unique name="uniqueKeyCode">
        <xs:selector xpath="move/* | wait | select"/>
        <xs:field xpath="."/>
    </xs:unique>
    

    这会起作用,因为您只选择 xs:selector 中的元素。

    使用 XSD 1.1,这可以使用 xs:assert 来完成,它允许您使用 xpath(选择器、字段、唯一性等仅允许您使用受限制的 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>
    

    【讨论】:

    • 非常感谢,这正是我所需要的!非常感谢您花时间写下答案!
    猜你喜欢
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 2023-03-23
    • 2012-09-09
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多