Вы не можете выполнить проверку, которую вы ищете, только с помощью XML-схемы.
Согласно спецификации «Схема XML, часть 1: структуры» ...
Когда две или более частиц, содержащихся прямо или косвенно в {частицах} модельной группы, имеют идентичные имена элементов
как их {термин}, определения типа этих объявлений должны быть
так же.
Нельзя сказать, что вы не можете построить схему, которая будет проверять правильный документ. Это означает, что вы не можете создать схему, которая не сможет проверить некоторые некорректные документы. И когда я говорю «неверно», я имею в виду документы, которые нарушают ограничения, изложенные вами на английском языке.
Например, предположим, у вас есть документ, который включает три элемента Street, например:
<Address Field="Street" Value="123 Main"/>
<Address Field="Street" Value="456 Main"/>
<Address Field="Street" Value="789 Main"/>
<Address Field="SomeOtherCrazyValue" Value="Foo"/>
Согласно вашей схеме, этот документ является действительным адресом. Можно добавить ограничение xs: unique в вашу схему, чтобы оно отклоняло такие поврежденные документы. Но даже при наличии xs: unique проверка по такой схеме объявила бы, что некоторые другие некорректные документы являются действительными - например, документ с тремя <Address>
элементами, каждый из которых имеет уникальный атрибут Field
, но ни один из которых не имеет Field="Zip"
.
На самом деле невозможно создать XML-схему W3C, которая формально кодифицирует ваши заявленные ограничения. Элемент <xs:all>
почти дает вам шанс, но он применяется только к элементам, а не к атрибутам. И его нельзя использовать с расширением, так что вы не можете сказать, в XML-схеме W3C, «все эти элементы в любом порядке, плюс любые другие».
Чтобы выполнить проверку, которую вы ищете, у вас есть следующие варианты:
- полагаться на что-то отличное от XML-схемы,
- выполнить проверку в несколько этапов, используя XML-схему для первого шага и что-то еще для второго шага.
Для первого варианта, я думаю, вы могли бы использовать Relax NG, чтобы сделать это. Недостатком этого является то, что это не стандарт, и, насколько я могу судить, он не получил широкой поддержки и не растет. Это все равно что учить гэльский, чтобы выразить мысль. В гэльском нет ничего плохого, но это своего рода лингвистический тупик, и Я думаю, что RelaxNG тоже .
Для второго варианта подход будет заключаться в проверке вашей схемы в качестве первого шага, а затем в качестве второго шага:
A. применить XSL-преобразование, которое преобразует <Address>
элементов в элементы, названные по значению их атрибута Field. Результат этого преобразования будет выглядеть так:
<root>
<Street Value="101 Bellavista Drive"/>
<State Value="Confusion"/>
<Zip Value="10101"/>
</root>
B. проверить вывод этого преобразования по другой схеме, которая выглядит примерно так:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element maxOccurs="1" minOccurs="1" ref="Street" />
<xs:element maxOccurs="1" minOccurs="1" ref="State" />
<xs:element maxOccurs="1" minOccurs="1" ref="Zip" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="Street">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="State">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="Zip">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
Вам потребуется расширить эту схему для обработки других элементов, таких как <SomeOtherCrazyValue>
в выходных данных преобразования. Или вы можете структурировать xsl-преобразование так, чтобы оно не испускало элементы, которые не являются элементами {State, Street, Zip}.
Просто чтобы прояснить, я понимаю, что вы не можете изменить полученный XML. Этот подход не требует этого. Он просто использует причудливый двухэтапный подход к валидации. После завершения 2-го шага проверки вы можете отказаться от результата преобразования.
EDIT - На самом деле, Шон, подумав еще раз, вы можете просто использовать шаг B. Предположим, что ваше XSL-преобразование просто Удаляет из документа только <Address>
элементов, которые не иметь значение State, Street или Zip для значения атрибута Field. Другими словами, не было бы <Address Field="SomeOtherCrazyValue"...>
. Результат этого преобразования может быть проверен вашей схемой, используя maxOccurs = "3", minOccurs = "3" и xs: unique.