views:

726

answers:

4

I need your help to define a special case in XML schema: A sequence that contains two elements: 'x' and 'y' whereas:

'x' element can appear 0 to unbound times in the sequence

'y' element can appear 0 to 1 time in the sequence

'x' and 'y' locations can be anywhere - that is, it is possible to have unbound times the 'x' element and then a single 'y' element, and then unbound times the 'x' element.

XML examples of this problem:

Example #1

< x >stuff< /x >

< y >stuff< /y>

< x >stuff< /x >

Example #2

< y >stuff< /y>

< x >stuff< /x >

< x >stuff< /x >

Example #3

< x >stuff< /x >

< x >stuff< /x >

< y >stuff< /y>

< x >stuff< /x >

Thanks!

A: 

Not too complicated. Off the top of my head, it should be something like this:

<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="y" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>

Since each element in XSD is optional by default, this XSD will match the XML structure you have defined, with the y element appearing anywhere before, after or between the x elements, with a maximum occurence of 1

Yuval A
Thanks for your answer, however I think it more complex then this. I have the error of:cos-nonambig: x and x (or elements from their substitution group) violate "Unique Particle Attribution". (note that your suggestion is all under "xsd:sequence")Do you have other idea instead?Thanks!
Ohad
Elements in XSD are not optional by default. Default is minOccurs="1". Added minOccurs="0" to each gives the problem that Oger states in his comment.
Alohci
@Alohci - thanks for the clarification
Yuval A
+2  A: 

EDIT: As Alohci mentioned, my solution is incorrect. According to the spec, an element in xs:all can only appear zero or one time. Sorry for any inconvenience

I think what you want isn't a sequence. A sequence defines not only the elements but also the order. And in your case the order may change. Have you tried xs:all?

<xs:complexType name="myComplexType">
  <xs:all>
    <xs:element name="x" type="xs:string" maxOccurs="unbounded"/>
    <xs:element name="y" type="xs:string" maxOccurs="1"/>
  </xs:all>
</xs:complexType>

Another appraoch might be to make it a sequence but mark the sequence to be maxOccurs="unbounded"

Mo
maxOccurs="unbounded" is not allowed in a xs:all group.
Alohci
A: 

It has been a while since I used schema, but I think sequences are your answer here.

You need to have an unbounded number of choices between (an x), or (a y followed by an x).

<xsd:element name="parent">
  <xsd:complexType>
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="x" type="xs:string"/>
      <xsd:sequence>
        <xsd:element name="y" type="xsd:string" />
        <xsd:element name="x" type="xsd:string" />
      </xsd:sequence>
    </xsd:choice>
  </xsd:complexType>  
</xsd:element>
davidsheldon
This does not allow the group to be a single "y" element, but does allow y-x-y-x as valid sequence which shouldn't be allowed.
Alohci
Ah yes, I was trying to solve the wrong problem.
davidsheldon
+4  A: 

For various reasons, none of Yuval's, Mo's or davidsheldon's samples work. Here's one that does.

    <xs:complexType name="myComplexType">
 <xs:sequence>
  <xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
  <xs:sequence minOccurs="0">
   <xs:element name="y" type="xs:string"/>
   <xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
 </xs:sequence>
    </xs:complexType>
Alohci
Hello Alohci - i am curious to why my solution doesn't work. Could you please share your concerns about that?
Mo
I have marked my solution. Thank you for the clarification
Mo