Проверка значения атрибута элемента XML в зависимости от атрибута дочернего элемента

У меня есть это в XML:

<generator Mode="High">
    <GenMode name="Normal" kV="90" mA="0.5" />
    <GenMode name="High" kV="160" mA="0.7" />
</generator>

generator/@mode должно быть действительным, только если оно соответствует одному из generator/GenMode/@name. Возможно ли это с XSD 1.0?

Теперь я использую эти правила в файле xsd для этого элемента:

<xs:element name="generator">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="GenMode" maxOccurs="unbounded" type="GenModeType" />
    </xs:sequence>
    <xs:attribute name="Mode" use="required" type="xs:string"/>
  </xs:complexType>
  <xs:key name="GenModeName">
    <xs:selector xpath="GenMode"/>
    <xs:field xpath="@name"/>
  </xs:key>
</xs:element>
<xs:complexType name="GenModeType">
  <xs:attribute name="name" use="required" type="xs:string"/>
  <xs:attribute name="kV" use="required" type="xs:integer"/>
  <xs:attribute name="mA" use="required" type="xs:decimal"/>
</xs:complexType>

person kot-da-vinci    schedule 22.06.2015    source источник
comment
Что вы имеете в виду под I want to check? Если в XML есть GenMode с тем же именем, что и у генератора/@mode, тогда он должен быть действительным или недействительным? Если вы хотите, чтобы один GenMode всегда имел то же имя, что и генератор/@mode, возможно, вы можете сделать это только с помощью XSD 1.1.   -  person sergioFC    schedule 22.06.2015
comment
@sergioFC generator/@mode должен быть действителен, только если один из GenMode имеет такое же имя.   -  person kot-da-vinci    schedule 22.06.2015
comment
Вам нужно будет использовать XSD 1.1. Лучшее, что я могу придумать в XSD1.0, — это определить тип генератора/@mode как xs:ID и добавить новый элемент GenMode в начале последовательности с типом GenMode/@mode как xs:IDREF.   -  person sergioFC    schedule 22.06.2015


Ответы (2)


Я думаю, что самое близкое, что вы можете сделать в XSD 1.0 без создания элементов с разными именами, это определить, что generator/@Mode должен ссылаться на первый GenMode/@name:

<xs:element name="generator">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="GenMode" type="GenModeType">
                <!-- This is the key of the first GenMode -->
                <xs:key name="firstGenModeKey">
                    <xs:selector xpath="."/>
                    <xs:field xpath="@name"/>
                </xs:key>
            </xs:element> 
            <xs:element name="GenMode" minOccurs="0" maxOccurs="unbounded" type="GenModeType" />
        </xs:sequence>
        <xs:attribute name="Mode" use="required" type="xs:string"/>
    </xs:complexType>
    <!-- Mode attribute should refer to firstGenModeKey -->
    <xs:keyref refer="firstGenModeKey" name="ign">
        <xs:selector xpath="."/>
        <xs:field xpath="@Mode"/>
    </xs:keyref>
    <!-- Every genMode/@name should be unique, so you can use xs:unique also -->
    <xs:key name="GenModeName">
        <xs:selector xpath="GenMode"/>
        <xs:field xpath="@name"/>
    </xs:key>
</xs:element>
<xs:complexType name="GenModeType">
    <xs:attribute name="name" use="required" type="xs:string"/>
    <xs:attribute name="kV" use="required" type="xs:integer"/>
    <xs:attribute name="mA" use="required" type="xs:decimal"/>
</xs:complexType>

Как вы знаете, если вы используете XSD 1.1, вам нужно добавить только одно утверждение, подобное этому примеру:

<xs:assert test="count(GenMode[@name = ../@Mode]) = 1"/>
person sergioFC    schedule 22.06.2015

Я нашел способ проверить значение атрибута с помощью XSD 1.0, и оно не должно относиться только к первому дочернему элементу.

<xs:element name="generator">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="GenMode" maxOccurs="unbounded" type="GenModeType"/>
    </xs:sequence>
    <xs:attribute name="Mode" use="required" type="xs:string"/>
  </xs:complexType>
  <xs:unique name="GenModeNameUniquenessCheck">
    <!-- check for uniqueness @name attribute of all GenMode elements -->
    <xs:selector xpath="GenMode"/>
    <xs:field xpath="@name"/>
  </xs:unique>
  <xs:keyref name="GeneratorModeValid" refer="GenModeNameUniquenessCheck">
    <!-- check generator/@Mode is one of generator/GenMode/@name  -->
    <xs:selector xpath="."/>
    <xs:field xpath="@Mode"/>
  </xs:keyref>     
</xs:element>
<xs:complexType name="GenModeType">
  <xs:attribute name="name" use="required" type="xs:string"/>
  <xs:attribute name="kV" use="required" type="xs:integer"/>
  <xs:attribute name="mA" use="required" type="xs:decimal"/>
</xs:complexType>
person kot-da-vinci    schedule 13.05.2016