Alternatywne sformułowanie pytania dodanego w późniejszej edycji wydaje się nadal pozostawać bez odpowiedzi: jak sprecyzować, że wśród elementów potomnych elementu musi być jeden nazwany child3
, jeden nazwany child4
i jakakolwiek nazwana liczba child1
lub child2
, bez ograniczenia kolejności w które pojawiają się dzieci.
Jest to łatwo definiowalny język regularny, a model treści, którego potrzebujesz, jest izomorficzny z wyrażeniem regularnym definiującym zestaw ciągów, w których cyfry „3” i „4” występują dokładnie raz, a cyfry „1” i „2” 'występują dowolną liczbę razy. Jeśli nie jest oczywiste, jak to napisać, warto pomyśleć o rodzaju skończonej maszyny stanowej, którą można by zbudować, aby rozpoznawać taki język. Miałoby co najmniej cztery różne stany:
- stan początkowy, w którym nie zaobserwowano ani „3”, ani „4”
- stan pośredni, w którym widać „3”, ale nie „4”
- stan pośredni, w którym widać „4”, ale nie „3”
- stan końcowy, w którym widać zarówno „3”, jak i „4”
Bez względu na stan automatu można odczytać „1” i „2”; nie zmieniają stanu maszyny. W stanie początkowym akceptowana będzie również wartość „3” lub „4”; w stanach pośrednich dopuszcza się tylko „4” lub „3”; w ostatecznym stanie ani „3”, ani „4” nie są akceptowane. Struktura wyrażenia regularnego jest najłatwiejsza do zrozumienia, jeśli najpierw zdefiniujemy wyrażenie regularne dla podzbioru naszego języka, w którym występuje tylko „3” i „4”:
(34)|(43)
Aby umożliwić wystąpienie „1” lub „2” dowolną liczbę razy w danym miejscu, możemy wstawić (1|2)*
(lub [12]*
jeśli nasz język regex akceptuje tę notację). Wstawiając to wyrażenie we wszystkich dostępnych lokalizacjach, otrzymujemy
(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*
Przełożenie tego na model treści jest proste. Podstawowa struktura jest odpowiednikiem wyrażenia regularnego (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>
Wstawienie opcji równej zero lub więcej child1
i child2
jest proste:
<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>
Jeśli chcemy nieco zminimalizować masę, możemy zdefiniować nazwaną grupę dla powtarzających się wyborów child1
i 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>
W XSD 1.1 niektóre ograniczenia na all
-groups zostały zniesione, więc możliwe jest bardziej zwięzłe zdefiniowanie tego modelu zawartości:
<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>
Ale jak widać na podanych wcześniej przykładach, te zmiany w all
-grupach w rzeczywistości nie zmieniają ekspresyjnej siły języka; uściślają jedynie definicje niektórych rodzajów języków.