0

I have the following XSD schema:

<xsd:schema xmlns="http://www.mynamespace.test/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.mynamespace.test/" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xsd:include schemaLocation="../Components.xsd"/>
    <xsd:element name="PO" type="POType"/>
    <xsd:complexType name="POType">
        <xsd:sequence>
            <xsd:element ref="PA" maxOccurs="unbounded"/>
            <xsd:element ref="PB" maxOccurs="unbounded"/>
            <xsd:any minOccurs="0" />
        </xsd:sequence>
        <xsd:attributeGroup ref="SomeAttrGroup"/>
        <xsd:attributeGroup ref="SomeOtherAttrGroup"/>
    </xsd:complexType>
</xsd:schema>

Where I basically want to make sure that my PO element contains PA elements and PB elements (PA before PB), where there are any kind of elements allowed to be in front of PA, in between PA and PB and after PB... I tried adding xsd:any at all those places, but even only one of them is not possible because of "Unique Particle Attribution".

I understand why this raises an error (can't tell the difference between an existing PB element to belong to the ANY part or the actual PB in the sequence). But I see no way of how to achieve what I actually want: is it possible at all, and how would it be done?

PS: The ANY elements can be in the same namespace as the PA and PB elements, just not the PA/PB elements itself.

CounterFlame
  • 1,612
  • 21
  • 31

2 Answers2

2

Where I basically want to make sure that my PO element contains PA elements and PB elements (PA before PB), where there are any kind of elements allowed to be in front of PA, in between PA and PB and after PB...

You cannot do this in XSD 1.0, but you can do this in XSD 1.1 because of its relaxed Unique Particle Attribution requirements:

<xsd:schema xmlns="http://www.mynamespace.test/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            targetNamespace="http://www.mynamespace.test/" 
            elementFormDefault="qualified"
            attributeFormDefault="unqualified"
            xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" 
            vc:minVersion="1.1">
    <xsd:include schemaLocation="../Components.xsd"/>
    <xsd:element name="PO" type="POType"/>
    <xsd:complexType name="POType">
        <xsd:sequence>
            <xsd:any minOccurs="0" />
            <xsd:element ref="PA" maxOccurs="unbounded"/>
            <xsd:any minOccurs="0" />
            <xsd:element ref="PB" maxOccurs="unbounded"/>
            <xsd:any minOccurs="0" />
        </xsd:sequence>
        <xsd:attributeGroup ref="SomeAttrGroup"/>
        <xsd:attributeGroup ref="SomeOtherAttrGroup"/>
    </xsd:complexType>
</xsd:schema>
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • Thanks a lot. Had some trouble finding an actual working XSD 1.1 implementation for Java, but it delivers the expected result at last. – CounterFlame Nov 10 '16 at 15:24
0

As it turned out this was not possible in XSD 1.0, I further investigated the features of XSD 1.1.

I'd like to thank kjhughes for his answer (which works, but isn't very user friendly when having large sequences, ...) and pointing me in the right direction, but it turns out that XSD 1.1 has something especially designed for this kind of behaviour:

OpenContents (see: XML Schema 1.1, Part 3: An introduction to XML Schema 1.1 and this answer here: How to ignore the validation of unknown tags )

To allow unknown elements, you can use an Open Content on your complexType.

<xsd:complexType name="CatalogEntry">
    <xsd:openContent mode="interleave">
        <xsd:any namespace="##any" processContents="skip"/>
    </xsd:openContent>

    <xsd:sequence>
        <xsd:element name="artist" type="xsd:string"/>
        <xsd:element name="album" type="xsd:string"/>
        <xsd:element name="price" type="xsd:decimal"/>
        <xsd:element name="release_date" type="xsd:dateTime"/>
    </xsd:sequence>
    <xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>

Specify mode interleave to allow unknown elements anywhere in between, or suffix to only allow elements at the end of the sequence.

There's also the option to specify a defaultOpenContent for a whole schema:

<xsd:schema ...>
    ...
    <xsd:defaultOpenContent mode="interleave">
        <xsd:any namespace="##any" processContents="skip"/>
    </xsd:defaultOpenContent>
    ...
    <xsd:complexType name="CatalogEntry">
        <xsd:sequence>
            <xsd:element name="artist" type="xsd:string"/>
            <xsd:element name="album" type="xsd:string"/>
            <xsd:element name="price" type="xsd:decimal"/>
            <xsd:element name="release_date" type="xsd:dateTime"/>
        </xsd:sequence>
        <xsd:attribute name="id" type="xsd:string"/>
    </xsd:complexType>
    <xsd:element name="cd" type="tns:CatalogEntry"/>
    ...
</xsd:schema>
Community
  • 1
  • 1
CounterFlame
  • 1,612
  • 21
  • 31