关于xpath:如何基于其他元素中的属性值来限制XML属性的值?

How can I restrict the values of an XML attribute based on attribute values in other elements?

我有这样的XML元素:

1
2
3
<characteristic name="Length"... />
<characteristic name="Width"... />
<!-- etc. -->

是否可以将另一个属性的值限制为(XPath)" // characteristic / @ name"的值之一?

因此将被允许:

1
2
3
<widget>
    <characteristic name="Length">100</characteristic>
</widget>

但这是不允许的:

1
2
3
<widget>
    <characteristic name="Bananas">33</characteristic>
</widget>

(因为"香蕉"不是名称特征之一。)

我假设可以使用" key"和" keyref"完成此操作,但是当键和ref均为属性值时,我不确定如何实现此功能。

此外,如果特征在与小部件不同的XML文档中列出,该怎么办? (甚至有可能吗?)理想情况下,我想使用XSD 1.0,但是我想知道XSD 1.1是否在此处添加了有用的东西。


这是一个示例架构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<xs:schema
  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="characteristics">
          <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
              <xs:element name="characteristic">
                <xs:complexType>
                  <xs:attribute name="name" type="xs:string"/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="widgets">
          <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
              <xs:element name="widget">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="characteristic">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:integer">
                            <xs:attribute name="name" type="xs:string"/>
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:key name="cname">
      <xs:selector xpath="characteristics/characteristic"/>
      <xs:field xpath="@name"/>
    </xs:key>
    <xs:keyref name="cname-ref" refer="cname">
      <xs:selector xpath="widgets/widget/characteristic"/>
      <xs:field xpath="@name"/>
    </xs:keyref>
  </xs:element>

</xs:schema>

应用于实例时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<root>
  <characteristics>
    <characteristic name="Length"/>
    <characteristic name="Width"/>
  </characteristics>
  <widgets>
    <widget>
        <characteristic name="Length">100</characteristic>
    </widget>

    <widget>
        <characteristic name="Bananas">33</characteristic>
    </widget>
  </widgets>
</root>

Xerces报告您要的错误:" test2014010301.xml:15:cvc-identity-constraint.4.3:找不到元素\\'Bananas \\'值为值\\'Bananas \\'的键\\'cname-ref \\'根\\'。"


在XSD 1.0中,您可能无法做到这一点(但是我不确定,因为我不确定"受控"特性与"控制"特性之间的关系:您可能会建议使用key / keyref来实现)。

在XSD 1.1中,可以使用断言或条件类型分配来完成。

XSD 1.1当前在Saxon,Xerces和Altova中实现。