tags:

views:

201

answers:

2

How can I design my xsd to ignore the sequence of elements?

<root> <a/> <b/> </root>

<root> <b/> <a/> </root>

I need to use extension for code generation reasons, so I tried the following using all:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.com/test"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:t="http://www.example.com/test" >

    <xs:complexType name="BaseType">
        <xs:all>
            <xs:element name="a" type="xs:string" />
        </xs:all>
    </xs:complexType>

    <xs:complexType name="ExtendedType">
        <xs:complexContent>
            <xs:extension base="t:BaseType">
                <xs:all> <!-- ERROR -->
                    <xs:element name="b" type="xs:string" />
                </xs:all>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

    <xs:element name="root" type="t:ExtendedType"></xs:element>
</xs:schema>

This xsd is not valid though, the following error is reported at <!-- ERROR -->:

cos-all-limited.1.2: An all model group must appear in a particle with {min occurs} = {max occurs} = 1, and that particle must be part of a pair which constitutes the {content type} of a complex type definition.

Documentation of cos-all-limited.1.2 says:

1.2 the {term} property of a particle with {max occurs}=1 which is part of a pair which constitutes the {content type} of a complex type definition.

I don't really understand this (neither xsd nor English native speaker :) ).


Am I doing the wrong thing, am I doing the right thing wrong, or is there no way to achieve this?
Thanks!

+1  A: 

MAJOR EDIT Originally I missed the requirement that you need to use xsd:extension. Note that xsd:extension works as if there was xsd:sequence with contents of the base type followed by contents of the extended type. As XML Schema Primer puts it:

When a complex type is derived by extension, its effective content model is the content model of the base type plus the content model specified in the type derivation. Furthermore, the two content models are treated as two children of a sequential group.

Therefore, it seems that the only way to make this work is to have an empty base type and store the whole alternative in the extended type, or vice versa (everything in the base and an empty extension). Like this:

<xsd:complexType name="ExtendedType">
   <xsd:complexContent>
      <xsd:extension base="BaseType">
         <xsd:choice>
            <xsd:sequence>
               <xsd:element name="a" type="xsd:string"/>
               <xsd:element name="b" type="xsd:string"/>
            </xsd:sequence>
            <xsd:sequence>
               <xsd:element name="b" type="xsd:string"/>
               <xsd:element name="a" type="xsd:string"/>
            </xsd:sequence>
         </xsd:choice>
      </xsd:extension>
   </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="BaseType"/>

<xsd:element name="root" type="ExtendedType"/>
Bolo
@Bolo: Thanks, but this one does not use `xs:extension`, so I can't use it.
Peter Lang
@Peter Right, I missed that part. Here's an update.
Bolo
@Bolo: Thanks for your update. Unfortunately I need to define some elements in the base type, and some in the extended, so unless there is another way, the elements of the extended type will always have to be placed after the elements of the base type...
Peter Lang
@Peter In that case, since "two content models are treated as two children of a sequential group", there is no way (as far as I can see) to ignore the sequence.
Bolo
@Bolo: I already assumed that... Maybe someone else has any ideas, otherwise I am gonna stick with my solution and force the "correct" sequence of the elements. Thanks for your time, really appreciated!
Peter Lang
A: 

<xs:complexType name="BaseType"> 
    <xs:sequence> 
        <xs:element name="a" type="xs:string" /> 
    </xs:sequence> 
</xs:complexType> 

<xs:complexType name="ExtendedType"> 
    <xs:complexContent> 
        <xs:extension base="t:BaseType"> 
            <xs:sequence> 
                <xs:element name="b" type="xs:string" /> 
            </xs:sequence> 
        </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

<xs:element name="root" type="t:ExtendedType"></xs:element> 

Ruslan
@Ruslan: Have you tried this? It will enforce the sequence of `a` before `b`, so it does not actually help me...
Peter Lang