В течение нескольких последних недель плотно занимался XML Schema – нужно было описать интерфейс взаимодействия двух компонент системы. В процессе узнал одну полезную вещь, которой хочу поделиться с общественностью.
Вещь эта называется – unordered sequences, а точнее рецепт их описания.

Проблема

Итак, для начала немного о проблеме. Как известно, в XML Schema есть 3 базовых варианта описания содержимого составного (complex) элемента: all, choice, sequence.
Первый вариант означает, что элементы могут встречаться в любом порядке, но каждый элемент не более, чем один раз. Второй вариант предоставляет возможность выбора между несколькими элементами. Последний вариант (наиболее используемый) позволяет задать строго упорядоченную (ordered) последовательность элементов, при этом каждый элемент может встречаться неограниченное число раз (по-умолчанию 1).
Всё бы было хорошо, если бы не ограничение на упорядоченность в sequence. Что делать, если элементы могут встречаться в произвольном порядке и при этом неограниченное кол-во раз? Ни all, ни sequence тут не подходят.
Согласитесь, вполне законное желание, но основательно погуглив я смог найти решение только в каком-то списке рассылки (да и то сообщения года эдак 2002). Странно, что на том же w3schools об этой проблеме – ни слова.

Решение

Наконец, решение. Оказывается, атрибуты minOccurs и maxOccurs могут иметь не только <xs:element>, но и элементы задающие упомянутие индикаторы (<xs:all>, <xs:choice>, <xs:sequence>).
Нас устроят следующие варианты (запишем для начала в виде регулярных выражений):

  1. (A|B)*
  2. (A?B?)*

Первый вариант описывается при помощи choice:

 <xs:choice minOccurs="0" maxOccurs="unbounded">
  <xs:element name="A"/>
  <xs:element name="B"/>
 </xs:choice>

Второй – при помощи sequence:

 <xs:sequence minOccurs="0" maxOccurs="unbounded">
  <xs:element name="A" minOccurs="0"/>
  <xs:element name="B" minOccurs="0"/>
 </xs:sequence>

Вуаля, так сказать.

Advertisements