constrain one out of two elements or both(but not zero)

This should cover W3C XML Schema, Relax NG and DTD related problems.
pag
Posts: 2
Joined: Tue Jul 18, 2006 1:33 pm

constrain one out of two elements or both(but not zero)

Post by pag »

Hi, all

I need schema to forse one of elements to have exactly one out of two provided elements or both of them (in any order), but not zero.

I tried:
<xsd:element name="parent">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="fooT" minOccurs="0"/>
<xs:element name="bar" type="barT" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xsd:element>

But, this allows also zero elements.

Also tried:
<xsd:element name="parent">
<xs:complexType>
<xs:choice>
<xs:element name="foo" type="fooT"/>
<xs:element name="bar" type="barT"/>
<xs:group ref="foo_and_bar"/>
</xs:choice>
</xs:complexType>
</xsd:element>
<xs:group name="foo_and_bar">
<xs:sequence>
<xs:element name="foo" type="fooT"/>
<xs:element name="bar" type="barT"/>
</xs:sequence>
</xs:group>

But this gives me error: "content model non-deterministic (possible causes: name equality, overlapping occurance or substitution groups)".
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Post by george »

You should write that as
(a, b?)|(b, a?)
In XML Schema following your example:

Code: Select all


  <xs:element name="parent">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="foo" type="fooT"/>
<xs:element name="bar" type="barT" minOccurs="0"/>
</xs:sequence>
<xs:sequence>
<xs:element name="bar" type="barT"/>
<xs:element name="foo" type="fooT" minOccurs="0"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
Best Regards,
George
pag
Posts: 2
Joined: Tue Jul 18, 2006 1:33 pm

Post by pag »

Thanks, george.

This solved my issue but I still wonder if it's possible to solve this puzzle if order DOES matters.
I.e. it is allowed to have:
<foo/>
<bar/>
--- or
<foo/>
--- or
<bar/>
--- but not
<bar/>
<foo/>

Provided solution doesn't work and following (just swapped two lines):

Code: Select all

<xs:choice>
<xs:sequence>
<xs:element name="foo" type="fooT"/>
<xs:element name="bar" type="barT" minOccurs="0"/>
</xs:sequence>
<xs:sequence>
<xs:element name="foo" type="fooT" minOccurs="0"/>
<xs:element name="bar" type="barT"/>
</xs:sequence>
</xs:choice>
... gives the same error I specified.

Ideas?
sorin_ristache
Posts: 4141
Joined: Fri Mar 28, 2003 2:12 pm

Post by sorin_ristache »

Hello,

In that case just write (a, b?) | (b) like the following example:

Code: Select all

<xs:element name="parent">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="foo" type="fooT"/>
<xs:element name="bar" type="barT" minOccurs="0"/>
</xs:sequence>
<xs:element name="bar" type="barT"/>
</xs:choice>
</xs:complexType>
</xs:element>
Regards,
Sorin
Post Reply