XML-схема: я могу заставить некоторые значения атрибута требоваться, но все еще позволить другие значения?

(Примечание: Я не могу изменить структуру XML, который я получаю. Я только могу измениться, как я проверяю его.)

Скажем, я могу получить XML как это:

<Address Field="Street" Value="123 Main"/>
<Address Field="StreetPartTwo" Value="Unit B"/>
<Address Field="State" Value="CO"/>
<Address Field="Zip" Value="80020"/>
<Address Field="SomeOtherCrazyValue" Value="Foo"/>

Я должен создать схему XSD, которая проверяет ту "улицу", "состояние" и "Zip" должны присутствовать. Но я не забочусь, присутствует ли любой "StreetPartTwo" и/или "SomeOtherCrazyValue", оказывается, также.

Если бы я знал, что только три, о которых я забочусь, могли быть включены (и что каждый будет только включен однажды), то я мог сделать что-то вроде этого:

<xs:element name="Address" type="addressType" maxOccurs="unbounded" minOccurs="3"/>

<xs:complexType name="addressType">
  <xs:attribute name="Field" use="required">
    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="Street"/>
        <xs:enumeration value="State"/>
        <xs:enumeration value="Zip"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:attribute>
</xs:complexType>

Но это не будет работать с моим случаем, потому что я могу также получить те другие элементы Адреса (которые также имеют "Полевые" атрибуты), что я не забочусь о.

Какие-либо идеи, как я могу гарантировать материал, о котором я забочусь, присутствуют, но впускают другой материал также?

TIA! Sean

8
задан scrotty 6 May 2010 в 04:35
поделиться

1 ответ

Вы не можете выполнить требуемую проверку, используя только XML-схему.

В соответствии со спецификацией «Схема XML, Часть 1: Структуры» ...

Когда две или более частиц, прямо или косвенно содержащихся в {частях} группы моделей, имеют объявления элементов с одинаковыми именами. в качестве их {term}, определения типов этих объявлений должны быть одинаковыми.

Это не означает, что вы не можете построить схему, которая проверяет правильность документа. Это означает, что вы не можете построить схему, которая не будет проверяться на некоторых неверных документах. И когда я говорю «неверно», я имею в виду документы, которые нарушают ограничения, указанные вами на английском языке.

Например, предположим, что у вас есть документ, который включает три элемента 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 проверка по такой схеме объявила бы, что некоторые другие неверные документы действительны - например, документ с тремя элементами

, каждый из которых имеет уникальное поле . , но ни один из них не имеет Field = "Zip" .

Фактически невозможно создать схему W3C XML, которая формально кодифицирует установленные вами ограничения. Элемент почти помогает вам понять, но он применяется только к элементам, а не к атрибутам. И его нельзя использовать с расширением, поэтому вы не можете сказать в схеме W3C XML «все эти элементы в любом порядке плюс любые другие».


Для выполнения требуемой проверки у вас есть следующие варианты:

  1. полагаться на что-то другое, кроме схемы XML,
  2. выполнять проверку в несколько этапов, используя схему XML для первого шага и что-то еще для второго. шаг.

Что касается первого варианта, я думаю, вы могли бы использовать Relax NG. Обратной стороной является то, что это не стандарт, и, насколько я могу судить, он не пользуется широкой поддержкой и не расширяется. Это было бы похоже на изучение гэльского языка, чтобы выразить мысль. В гэльском нет ничего плохого, но это своего рода лингвистический тупик, и я думаю, что RelaxNG тоже .

Для второго варианта подход будет заключаться в проверке соответствия вашей схеме в качестве первого шага, а затем, в качестве второго шага:

A. применить преобразование XSL, которое преобразует элементы

в элементы, названные по значению их атрибута 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>

Вам нужно будет расширить эту схему для обработки других элементов, таких как на выходе преобразования. Или вы можете структурировать преобразование xsl, чтобы просто не генерировать элементы, не относящиеся к {State, Street, Zip}.

Чтобы внести ясность, я понимаю, что вы не можете изменить полученный XML. Такой подход не требует этого. Он просто использует забавный двухэтапный подход к проверке. После завершения 2-го шага проверки вы можете отбросить результат преобразования.


РЕДАКТИРОВАТЬ - На самом деле, Шон, подумав об этом еще раз, вы можете просто использовать шаг B. Предположим, ваше XSL-преобразование просто удаляет из документа только

элементы которые не имеют State, Street или Zip для значения атрибута Field. Другими словами, не было бы
. Результат этого преобразования можно проверить с помощью вашей схемы, используя maxOccurs = "3", minOccurs = "3" и xs: unique.

6
ответ дан 5 December 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: