Создание XML-схемы с атрибутами и элементами, зависящими от других атрибутов - PullRequest
9 голосов
/ 21 октября 2009

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

Реальные данные довольно абстрактны, поэтому я создал несколько простых примеров. Допустим, у меня есть следующие XML-файлы:

<?xml version="1.0" encoding="UTF-8"?>
<Creature type="human" nationality="British">
    <Address>London</Address>
</Creature>

<?xml version="1.0" encoding="UTF-8"?>
<Creature type="animal" species="Tiger">
    <Habitat>Jungle</Habitat>
</Creature>

Если "тип" существа - "человек", у меня будет атрибут "национальность" и дочерний элемент "Адрес". Если «тип» существа - «животное», у меня будет атрибут «вид» и дочерний элемент «среда обитания». Для целей этого примера «человек» с «видом» или «средой обитания» будет недействительным, как и «животное» с «национальностью» или «адресом».

Если бы «Существо» не было корневым элементом, я мог бы иметь два разных варианта «Существо» ниже корневого элемента, но я не понимаю, как я могу заставить эту работу работать, когда «Существо» является корневым элементом.

Есть ли способ создать схему для этих файлов, которая бы соответствовала только действительным документам? Если так, как бы я поступил об этом?

1 Ответ

7 голосов
/ 21 октября 2009

Для этой цели вы можете использовать атрибут xsi: type (вам придется использовать xsi: type из пространства имен экземпляра XMLSchema, а не из собственного пространства имен, иначе он не будет работать).

В схеме вы объявляете базовый тип, который объявлен как абстрактный, и создаете дополнительные сложные типы для каждого подтипа (с элементами / атрибутами, специфичными для этого типа).

Имейте в виду, что, хотя это решение работает, было бы лучше использовать разные имена элементов для каждого типа (xsi: type является своего рода противодействующим зерном, поскольку теперь он является атрибутом типа в сочетании с именем элемента, которое определяет тип, а не просто имя элемента).

например:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="Creature" type="CreatureType">
</xs:element>

  <xs:complexType name="CreatureType" abstract="true">
    <!-- any common validation goes here -->
  </xs:complexType>

  <xs:complexType name="Human">
    <xs:complexContent>
      <xs:extension base="CreatureType">
        <xs:sequence maxOccurs="1">
          <xs:element name="Address"/>
        </xs:sequence>
        <xs:attribute name="nationality" type="xs:string"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Animal">
    <xs:complexContent>
      <xs:extension base="CreatureType">
        <xs:sequence maxOccurs="1">
          <xs:element name="Habitat"/>
        </xs:sequence>
        <xs:attribute name="species" type="xs:string"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

</xs:schema>

Эта схема будет проверять эти два:

<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:type="Human" 
          nationality="British">
    <Address>London</Address>
</Creature>

<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:type="Animal" 
          species="Tiger">
    <Habitat>Jungle</Habitat>
</Creature>

но не это:

<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:type="SomeUnknownThing" 
          something="something">
    <Something>Something</Something>
</Creature>

или это:

<?xml version="1.0" encoding="UTF-8"?>
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="Human" 
          species="Tiger">
    <Habitat>Jungle</Habitat>
</Creature>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...