Альтернативная формулировка вопроса, добавленная в более поздней редакции, по-прежнему остается без ответа: как указать, что среди дочерних элементов элемента должен быть один с именем child3
, один с именем child4
и любое число с именем child1
или child2
, без ограничений по порядку появления детей.
Это понятный регулярный язык, и нужная вам модель содержимого изоморфна регулярному выражению, определяющему набор строк, в которых цифры «3» и «4» встречаются ровно один раз, а цифры «1» и «2» встречаются любое количество раз. Если не совсем понятно, как написать это, это может помочь подумать о том, какой тип конечного автомата вы бы построили для распознавания такого языка. Было бы как минимум четыре различных состояния:
- начальное состояние, в котором не было замечено ни «3», ни «4»
- промежуточное состояние, в котором было замечено «3», но не «4»
- промежуточное состояние, в котором «4» было замечено, но не «3»
- конечное состояние, в котором были видны и «3», и «4»
Независимо от того, в каком состоянии находится автомат, «1» и «2» могут быть прочитаны; они не меняют состояние машины. В исходном состоянии «3» или «4» также будут приняты; в промежуточных состояниях принимаются только «4» или «3»; в конечном состоянии ни «3», ни «4» не принимаются. Структуру регулярного выражения легче всего понять, если мы сначала определим регулярное выражение для подмножества нашего языка, в котором встречаются только «3» и «4»:
(34)|(43)
Чтобы разрешить '1' или '2' встречаться любое количество раз в данном месте, мы можем вставить (1|2)*
(или [12]*
, если наш язык регулярных выражений принимает эту запись). Вставляя это выражение во все доступные местоположения, мы получаем
(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*
Перевести это в модель контента просто. Базовая структура эквивалентна регулярному выражению (34)|(43)
:
<xsd:complexType name="paul0">
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
Вставить ноль или более вариантов child1
и child2
просто:
<xsd:complexType name="paul1">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
Если мы хотим немного уменьшить объем, мы можем определить именованную группу для повторяющихся вариантов child1
и child2
:
<xsd:group name="onetwo">
<xsd:choice>
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="paul2">
<xsd:sequence>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
В XSD 1.1 некоторые ограничения на all
-группы были сняты, поэтому можно определить эту модель контента более кратко:
<xsd:complexType name="paul3">
<xsd:all>
<xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child3"/>
<xsd:element ref="child4"/>
</xsd:all>
</xsd:complexType>
Но, как видно из приведенных ранее примеров, эти изменения в all
-группах фактически не изменяют выразительную силу языка; они только делают определение некоторых видов языков более кратким.