Samuel
Samuel

Reputation: 6490

XSD: Combine xs:group with xs:all?

I am struggling with a xsd where I want to combine a xs:group and a xs:all entry:

Sample XSD:

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

    <!-- This group will be reused later -->
    <xs:group name="TGroup">
        <xs:choice>
            <xs:element name="Mixable1" type="xs:string" />
            <xs:element name="Mixable2" type="xs:string" />
            <xs:element name="Mixable3" type="xs:string" />
        </xs:choice>
    </xs:group>

    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:group ref="TGroup" minOccurs="0" maxOccurs="unbounded" />
                <xs:all>
                    <xs:element name="RootContent1" type="xs:string" minOccurs="0" />
                    <xs:element name="RootContent2" type="xs:string" minOccurs="0" />
                </xs:all>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

(this does not validate as xs:all is not allowed in xs:sequence)

What I am trying to achieve: The root element should always allow RootContent1 and RootContent2 in an arbitrary order (therefore the xs:all) and each element should additionally be optional but would still allow all if necessary (in contrast to xs:choice)

Furthermore I need a reusable set of nodes (defined by the group TGroup) with an arbitrary amount of MixableX elements in any order. It is a xs:group because the group itself will be reused (in the real xsd) and I want to avoid duplication of declaration.

Some Sample XMLs

<root>
    <Mixable1 />
</root>

<root>
    <Mixable2 />
    <RootContent1 />
</root>

<root>
    <Mixable2 />
    <Mixable1 />
    <Mixable2 />
    <RootContent2 />
</root>

I have the feeling that what I want to describe is non-deterministic for the parser and therefore not representable with XSD but I might as well just missed something.

Upvotes: 2

Views: 3686

Answers (1)

parakmiakos
parakmiakos

Reputation: 3020

If you check this out : http://www.w3schools.com/schema/el_sequence.asp You will see that you are not allowed to nest xs:all inside of xs:sequence.

Also I tried tricking it by creating a group to contain the tag, but as it appears, (and also referenced in this post : XML Schema: all, sequence & groups)

XML Schema stipulates that an all group must appear as the sole child at the top of a content model.

But, if you don't plan on having RootContent1 & 2 simulatenously, then Filburt is right and you could simply go with another choice element:

<xs:element name="root">
    <xs:complexType>
        <xs:sequence>
            <xs:group ref="TGroup" minOccurs="0" maxOccurs="unbounded"/>
            <xs:choice minOccurs="0">
                <xs:element name="RootContent1" type="xs:string" minOccurs="0"/>
                <xs:element name="RootContent2" type="xs:string" minOccurs="0"/>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Edit: This could be a work around for this specific case

<xs:element name="root">
    <xs:complexType>
        <xs:sequence>
            <xs:group ref="TGroup" minOccurs="0" maxOccurs="unbounded"/>
            <xs:choice>
                <xs:sequence minOccurs="0">
                    <xs:element ref="RootContent1" minOccurs="0"/>
                    <xs:element ref="RootContent2" minOccurs="0"/>
                </xs:sequence>
                <xs:sequence minOccurs="0">
                    <xs:element ref="RootContent2" minOccurs="0"/>
                    <xs:element ref="RootContent1" minOccurs="0"/>
                </xs:sequence>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:element name="RootContent2" type="xs:string"/>
<xs:element name="RootContent1" type="xs:string"/>

Upvotes: 2

Related Questions