La formulación alternativa de la pregunta agregada en una edición posterior parece aún sin respuesta: cómo especificar que entre los hijos de un elemento, debe haber uno con nombre child3
, uno con nombre child4
y cualquier número con nombre child1
o child2
, sin restricción en el orden en que aparecen los niños.
Este es un lenguaje regular fácilmente definible, y el modelo de contenido que necesita es isomorfo a una expresión regular que define el conjunto de cadenas en el que los dígitos '3' y '4' ocurren exactamente una vez, y los dígitos '1' y '2 'ocurre cualquier número de veces. Si no es obvio cómo escribir esto, puede ser útil pensar en qué tipo de máquina de estados finitos construiría para reconocer dicho lenguaje. Tendría al menos cuatro estados distintos:
- un estado inicial en el que no se ha visto ni '3' ni '4'
- un estado intermedio en el que se ha visto '3' pero no '4'
- un estado intermedio en el que se ha visto '4' pero no '3'
- un estado final en el que se han visto tanto '3' como '4'
No importa en qué estado se encuentre el autómata, se pueden leer '1' y '2'; no cambian el estado de la máquina. En el estado inicial, también se aceptarán '3' o '4'; en los estados intermedios, solo se acepta '4' o '3'; en el estado final, no se aceptan ni '3' ni '4'. La estructura de la expresión regular es más fácil de entender si primero definimos una expresión regular para el subconjunto de nuestro lenguaje en el que solo aparecen '3' y '4':
(34)|(43)
Para permitir que '1' o '2' ocurra cualquier número de veces en una ubicación determinada, podemos insertar (1|2)*
(o [12]*
si nuestro lenguaje de expresiones regulares acepta esa notación). Al insertar esta expresión en todas las ubicaciones disponibles, obtenemos
(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*
Traducir esto a un modelo de contenido es sencillo. La estructura básica es equivalente a la expresión regular (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>
Insertar una opción cero o más de child1
y child2
es sencillo:
<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>
Si queremos minimizar un poco el volumen, podemos definir un grupo con nombre para las opciones repetidas de child1
y 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>
En XSD 1.1, se eliminaron algunas de las restricciones en los all
grupos, por lo que es posible definir este modelo de contenido de manera más concisa:
<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>
Pero como puede verse en los ejemplos dados anteriormente, estos cambios en los all
grupos no cambian de hecho el poder expresivo del lenguaje; sólo hacen más sucinta la definición de ciertos tipos de lenguajes.