Создание «гибкой» XML-схемы - PullRequest
4 голосов
/ 07 апреля 2010

Мне нужно создать схему для XML-файла, который будет достаточно гибким. Он должен соответствовать следующим требованиям:

  1. Проверьте некоторые элементы, которые нам необходимы, и узнайте точную структуру
  2. Проверьте некоторые элементы, которые являются необязательными, и мы знаем точную структуру
  3. Разрешить любые другие элементы
  4. Разрешить их в любом порядке

Быстрый пример:

XML

<person>
    <age></age>
    <lastname></lastname>
    <height></height>
</person>

Моя попытка XSD:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" minOccurs="0" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Теперь мой XSD удовлетворяет требованиям 1 и 3. Однако это недопустимая схема, если и имя, и фамилия были необязательными, поэтому он не удовлетворяет требованию 2, а порядок фиксирован, что не соответствует требованию 4.

Теперь все, что мне нужно, это что-то для проверки моего XML. Я открыт для предложений по любому способу сделать это, либо программно в .NET 3.5, схеме другого типа и т. Д.

Кто-нибудь может придумать решение для удовлетворения всех 4 требований?

Ответы [ 2 ]

6 голосов
/ 07 апреля 2010

Ваше требование № 3 не может быть выполнено, если элементы имени являются необязательными, потому что ваша схема будет тогда нарушать уникальное правило присвоения частиц (в основном, процессор не будет знать, проверять ли имя по имени или по любому).

Вы не ограничены одной схемой, что касается проверки.Если вы согласны с использованием двух схем в разных пространствах имен, вы можете сделать это:

Schema one - разрешить что угодно:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="document">
    <xs:complexType>
      <xs:sequence>
        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Schema two - добавить специальную проверку для некоторых элементов:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://other" xmlns="http://other">
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
</xs:schema>

Затем убедитесь, что ваш экземпляр xsi: include документа ссылается на обе схемы.

1 голос
/ 22 августа 2014

Я много думал об этой проблеме сегодня.Я размышлял о том, насколько трудно это правило xs:all заставляет базы данных XML хранить документы, которые имеют неструктурированные данные типа CMS, а также проверять данные.

Затем мне пришло в голову, что XHTML допускает очень гибкуюрасположение вложенных элементов в любом порядке, в котором вам нужно пометить страницу.

Итак, вот выдержка из схемы XHTML 1.1:

  <xs:group name="InlForm.class">
    <xs:choice>
      <xs:element ref="input"/>
      <xs:element ref="select"/>
      <xs:element ref="textarea"/>
      <xs:element ref="label"/>
      <xs:element ref="button"/>
    </xs:choice>
  </xs:group>

  <xs:group name="Inline.extra">
    <xs:choice/>
  </xs:group>

  <xs:group name="Ruby.class">
    <xs:sequence>
      <xs:element ref="ruby"/>
    </xs:sequence>
  </xs:group>

  <!--
   Inline.class includes all inline elements,
   used as a component in mixes
  -->
  <xs:group name="Inline.class">
    <xs:choice>
      <xs:group ref="InlStruct.class"/>
      <xs:group ref="InlPhras.class"/>
      <xs:group ref="InlPres.class"/>
      <xs:group ref="I18n.class"/>
      <xs:group ref="Anchor.class"/>
      <xs:group ref="InlSpecial.class"/>
      <xs:group ref="InlForm.class"/>
      <xs:group ref="Ruby.class"/>
      <xs:group ref="Inline.extra"/>
    </xs:choice>
  </xs:group>

  <xs:group name="Heading.class">
    <xs:choice>
      <xs:element ref="h1"/>
      <xs:element ref="h2"/>
      <xs:element ref="h3"/>
      <xs:element ref="h4"/>
      <xs:element ref="h5"/>
      <xs:element ref="h6"/>
    </xs:choice>
  </xs:group>

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

Надеюсь, это поможет.Я думаю, что это иллюстрирует, как супер-flexi-схемы «действительно» выполняются в XSD 1.0.

Редактировать - это работает!Вы можете создать «основную» группу из всех других групп и использовать этот пример определения элемента ListItem, чтобы разрешить непрерывно вложенные элементы в любом порядке.Убедитесь, что ListItem также включен в группу, чтобы рекурсия работала.

  <xs:element name="ListItem">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="content:any.mix"  minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

Итак, моя группа any.mix выглядит следующим образом:

  <xs:group name="any.mix">
    <xs:choice>      
      <xs:group ref="content:item.class" />
      <xs:group ref="content:media.class" />
      <xs:group ref="content:data.class" />
      <xs:group ref="content:list.class" />      
    </xs:choice>
  </xs:group>

И каждый из этих "классов"группы содержат еще больше вариантов выбора групп и т. д. и т. д. до тех пор, пока они в конце концов не достигнут элементов, если хотите, фактических тегов конечного уровня.

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

Люк

...