XSD断言对嵌套元素的属性是否相等?

问题描述

我正在尝试向XSD(1.1)模式添加一个断言,该断言将检查元素属性是否与其子元素的值相等。

我有以下XML:

<?xml version="1.0" encoding="UTF-8"?>

<CarList Maker="Tesla">
  <Car>
    <Year>2010</Year>
    <Color>Blue</Color>
    <Price>40000</Price>
    <Maker>Tesla</Maker>
  </Car>
  <Car>
    <Year>2011</Year>
    <Color>White</Color>
    <Price>20000</Price>
    <Maker>Tesla</Maker>
  </Car>
  <Car>
    <Year>2012</Year>
    <Color>Black</Color>
    <Price>55000</Price>
    <Maker>Tesla</Maker>
  </Car>
</CarList>

我想确保Maker元素的CarList属性是随后的Car元素中使用的唯一制造商。我使用XSD 1.1,因此尝试使用xs:assert进行以下操作:

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema  xmlns:xs="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"
            xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
            vc:minVersion="1.1">

<xs:element name="Year" type="xs:positiveInteger"/>
<xs:element name="Color" type="xs:string"/>
<xs:element name="Price" type="xs:positiveInteger"/>
<xs:element name="Maker" type="MakerType"/>

<xs:simpleType name="MakerType">
  <xs:restriction base="xs:string">
    <xs:enumeration value="Tesla"/>
    <xs:enumeration value="GM"/>
    <xs:enumeration value="Ford"/>
  </xs:restriction>
</xs:simpleType>

<xs:element name="Car">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="Year"/>
      <xs:element ref="Color"/>
      <xs:element ref="Price"/>
      <xs:element ref="Maker"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="CarList">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="Car" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="Maker" type="MakerType" use="required"/>
    <xs:assert test="Car/Maker eq @Maker"/>
  </xs:complexType>
</xs:element>

</xs:schema>

但是当我尝试验证它(使用python xmlschema库)时,出现以下错误

第1行第4列的

'/'运算符:[err:XPTY0004]原子化操作数是一个长度大于1的序列

test元素中xs:assert属性的XPath格式似乎有错误,更具体地说,我尝试访问子元素Maker的方式Car元素。

我在做什么错?知道我该如何完成这个断言吗?

解决方法

Car/Maker中的xs:assert XPath正在选择多个元素,这些元素不能直接与属性值@Maker进行比较。

要解决此问题,请从{p>更改您的xs:assert

<xs:assert test="Car/Maker eq @Maker"/>

<xs:assert test="every $maker in Car/Maker satisfies $maker eq @Maker"/>