Как определить взаимоисключающие атрибуты в XSD?


Сначала фрагмент кода...

<tag name="default" abc="10" def="20> <!-- not valid, abc and def should be mutually exclusive -->

<tag name="default1" abc="10"> <!-- valid -->

<tag name="default2" def="20> <!-- valid -->
То, что я хочу сделать...

Что я могу вложить в свой XSD так, чтобы @abc и @def не могли сосуществовать как атрибуты на одном и том же элементе?

Так что проверка будет неудачной, если они сосуществуют на одном и том же элементе?

2 7

2 ответа:

XSD 1.0

Можно сделать с помощью хитрого трюка xs:key. Смотрите ответ@Kachna .

Обратите внимание, что некоторые Парсеры могут разрешить оба атрибута, если они не завершаются ошибкой для нескольких выбранных значений в xs:key. Есть, по крайней мере, один известный случай, когда это происходило в прошлом.

XSD 1.1

Можно сделать с помощью xs:assert:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           vc:minVersion="1.1">
  <xs:element name="tag">
    <xs:complexType>
      <xs:sequence/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="abc" use="optional" type="xs:integer"/>      
      <xs:attribute name="def" use="optional" type="xs:integer"/>
      <xs:assert test="(@abc and not(@def)) or (not(@abc) and @def)"/>      
    </xs:complexType>
  </xs:element>
</xs:schema>

С помощью XSD 1.0 можно использовать элемент xs:key.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="tag">
    <xs:complexType>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="abc"  type="xs:integer"/>      
        <xs:attribute name="def"  type="xs:integer"/>
     </xs:complexType>
    <xs:key name="attributeKey">
        <xs:selector xpath="."/>
        <xs:field xpath="@abc|@def"/>
    </xs:key>
</xs:element>   

Редактировать: Если присутствуют оба атрибута (даже с разными значениями), это создает два ключа, поэтому проверка XML завершится неудачей. С другой стороны, <xs: key> требует, чтобы для элемента был определен ключ, и поэтому должен присутствовать один из двух атрибутов.

Следующий XML-документ недопустим при использовании вышеупомянутого XSD. (Я использую кислород 17.0):

<tag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="stack3.xsd" name="" abc="12" def="13"/>

Ошибка:

cvc-identity-constraint.3: Field "./@abc|./@def" of identity constraint "attributeKey" matches more than one value within the scope of its selector; fields must match unique values