Search code examples
xmlxsdxsd-validation

XSD give a choice between two different sequences


In my xsd file I want to specify that the parent_type can contain either 1-n children of utf8_text_type or 1-n children of xml_text_type. But one element cannot have children of both types at the same time.

<!-- PROHIBIT THIS -->
<text-parent>
    <text encoding="utf8">utf8 encoding</text>
    <text encoding="xml">xml encoding</text>
</text-parent>


<!-- ALLOW THIS -->
<text-parent>
    <text encoding="utf8">utf8 encoding</text>
</text-parent>


<text-parent>
    <text encoding="xml">xml encoding</text>
    <text encoding="xml">xml encoding</text>
</text-parent>

I created the following:

<xs:element name="text-parent" type="parent_type"/>

<xs:complexType name="parent_type">
    <xs:choice minOccurs="1" maxOccurs="1">
        <xs:sequence>
            <xs:element name="text" type="utf8_text_type" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:sequence>
            <xs:element name="text" type="xml_text_type" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:choice>
</xs:complexType>


<xs:complexType name="utf8_text_type" mixed="true">
    <xs:sequence>
        <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="encoding" fixed="utf8" use="required"/>
</xs:complexType>


<xs:complexType name="xml_text_type" mixed="true">
    <xs:sequence>
        <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="encoding" fixed="xml" use="required"/>
</xs:complexType>

The problem is that now the xsd only allows for utf8_text_type. If the xml_text_type is listed first then it only allows for that, so the first mentioned.

I tried to play around with the cardinalities, but that did not work.


Solution

  • This is not possible with XSD 1.0 because the validator has to decide between two choices based solely on the element name (or perhaps the xsi:type attribute), it cannot choose based on attribute values.

    There are many ways of tackling this using XSD 1.1 if that's an option for you.