首页 > 解决方案 > 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属性的 XPath 格式存在错误xs:assert,更具体地说,是我尝试访问元素的子元素Maker的方式Car

我究竟做错了什么?知道如何完成这个断言吗?

标签: xmlxsdxsd-validationxml-validationxsd-1.1

解决方案


您中的Car/MakerXPathxs:assert正在选择多个元素,这些元素无法直接与属性值进行比较,@Maker.

要修复,请更改您xs:assert

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

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

推荐阅读