Home All Groups Group Topic Archive Search About

XML Schema to describe specifc case

Author
15 Mar 2006 7:37 AM
Reuven Nisser
Hi,
How can I describe an XML like this:

<X>
    <Y/>
    <Z/>
    <Y/>
    <Y/>
</X>

I mean a case where Z appears once and Y appears zero or more times and
the order is not important. If Z might appear more than once I can use:

<xsi:choice minOccurs="0" maxOccurs="unbounded">

But I do not know what to do when it appears once.
Thanks,
Reuven Nisser

Author
15 Mar 2006 7:58 AM
George Bina
Hi,

You need a model like:

Y*,Z,Y*

In XML Schema that will be:

  <xs:element name="X">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Y" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="Z"/>
        <xs:element ref="Y" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

Best Regards,
George
---------------------------------------------------------------------
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
Author
15 Mar 2006 4:52 PM
Reuven Nisser
Hi,
Thanks, I thought it will be the answer but I hoped there is an easier
way. You see Y could be several items (Y1,Y2,Y3...) which means creating
a "choice" before and after the Z element.
Regards, Reuven
Author
15 Mar 2006 4:55 PM
Reuven Nisser
Hi,
Thanks, I thought it will be the answer but I hoped there is an easier
way. You see Y could be several items (Y1,Y2,Y3...) which means creating
a "choice" before and after the Z element.

And if Z is also several items (Z1,Z2,Z3,...) which can also appear once
everywhere I have a problem.

The complete script would be:
<X>
     <Y1/>
     <Z2/>
     <Y2/>
     <Y1/>
     <Z1/>
     <Y2/>
     <Y3/>
     <Z3/>
</X>

Regards, Reuven
Author
15 Mar 2006 10:44 PM
George Bina
Hi,

You cannot do this in XML Schema alone, but you can use a relaxed model
in the XML Schema and embedded Schematron rules to check that Z1, Z2,
Z3 elements appear once. Below is a working XML Schema with embedded
schematron rules that does that:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
  <xs:element name="X">
    <xs:annotation>
      <xs:appinfo>
        <pattern xmlns="http://www.ascc.net/xml/schematron" name="Check
          number of occurances">
          <rule context="X">
            <assert test="count(Z1)=1">There should be one occurence of
Z1 in X.</assert>
            <assert test="count(Z2)=1">There should be one occurence of
Z1 in X.</assert>
            <assert test="count(Z3)=1">There should be one occurence of
Z1 in X.</assert>
          </rule>
        </pattern>
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element ref="Y1"/>
        <xs:element ref="Y2"/>
        <xs:element ref="Y3"/>
        <xs:element ref="Z1"/>
        <xs:element ref="Z2"/>
        <xs:element ref="Z3"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:element name="Y1">
    <xs:complexType/>
  </xs:element>
  <xs:element name="Y2">
    <xs:complexType/>
  </xs:element>
  <xs:element name="Y3">
    <xs:complexType/>
  </xs:element>
  <xs:element name="Z1">
    <xs:complexType/>
  </xs:element>
  <xs:element name="Z2">
    <xs:complexType/>
  </xs:element>
  <xs:element name="Z3">
    <xs:complexType/>
  </xs:element>
</xs:schema>

You can also do this in Relax NG. Below are working schemas both in
compact syntax and in XML syntax.

Compact syntax:

start =
  element X {
    (element Z1 { text }
     & element Z2 { text }
     & element Z3 { text })
    & (element Y1 { text }
       | element Y2 { text }
       | element Y3 { text })*
  }

XML syntax:

<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
    <start>
        <element name="X">
            <interleave>
                <interleave>
                    <element name="Z1"><text/></element>
                    <element name="Z2"><text/></element>
                    <element name="Z3"><text/></element>
                </interleave>
                <zeroOrMore>
                    <choice>
                        <element name="Y1"><text/></element>
                        <element name="Y2"><text/></element>
                        <element name="Y3"><text/></element>
                    </choice>
                </zeroOrMore>
            </interleave>
        </element>
    </start>
</grammar>

Best Regards,
George
---------------------------------------------------------------------
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
Author
16 Mar 2006 1:53 AM
Kevin Yu [MSFT]
Hi Reuven,

Must the Z element always appear beside between Y blocks? Is the sequence
important? If so, I agree George that it is the only way to write such a
complex schema. If the sequence is not so important, I suggest you use

  <xs:element name="X">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Z"/>
        <xs:element ref="Y" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

which puts Z before the Y block. You can also add attribute in the Z
element to identify the sequence of Z.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

AddThis Social Bookmark Button