SwiftMango
SwiftMango

Reputation: 15284

How to make one of two optional tag dependent on the other?

I have two tags in XSD:

<xsd:element name="tag1" minOccurs="0">

<xsd:element name="tag2" minOccurs="0">

They are both optional and can be omitted. However I want to add a restriction that if tag2 is given, tag1 should also be given (as tag2 is dependent on tag1). How to achieve this by just XSD?


Edit:

There are mandatory tags between them. Thus a sequence will not work. e.g.

<xsd:element name="tag1" minOccurs="0">
<xsd:element name="tag3" minOccurs="1">
<xsd:element name="tag4" minOccurs="1">
<xsd:element name="tag2" minOccurs="0">

Upvotes: 1

Views: 176

Answers (1)

sergioFC
sergioFC

Reputation: 6016

Here are some solutions:

Use a choice

This is a long solution as it repeats parts of the model but it works if you really need mandatory tags between the optional tags and tags are not inside an xs:all:

<xsd:choice>

    <!-- Choice option 1: optional tags present -->
    <xsd:sequence>
        <xsd:element name="optionalTag1"/>
        <xsd:element name="complulsoryTag1"/>
        <xsd:element name="complulsoryTag2"/>
        <xsd:element name="optionalTag2"/>
    </xsd:sequence>

    <!-- Choice option 2: optional tags not present -->
    <xsd:sequence>
        <xsd:element name="complulsoryTag1"/>
        <xsd:element name="complulsoryTag2"/>
    </xsd:sequence>

</xsd:choice>

Note that you can avoid repeating tags on the model if you use an xs:group to group your complusory central tags.

Wrap tags in optional sequence

If there were not mandatory tags between them you could simply wrap them in a sequence with minOccurs=0. So if the sequence appears then both tags are present, and if the sequence doesn't appears none of the tags are present:

<xsd:sequence minOccurs="0">
    <xsd:element name="tag1"/>
    <xsd:element name="tag2"/>
</xsd:sequence>

Note that this won't work inside an xs:all but you can use it inside a choice or even inside another sequence if you want.

Use XSD 1.1 assertions

If your processor is using XSD 1.1 you can use xs:assert to ensure that either all of the optional tags are present or either none of them is present:

<xsd:complexType>
    <xsd:sequence>
        <xsd:element name="optionalTag1" minOccurs="0"/>
        <xsd:element name="complulsoryTag1"/>
        <xsd:element name="complulsoryTag2"/>
        <xsd:element name="optionalTag2" minOccurs="0"/>
    </xsd:sequence>
    <!-- Both optional tags are present or none of them are present -->
    <xsd:assert test="boolean(optionalTag1) = boolean(optionalTag2)"/>
</xsd:complexType>

Note that this is the only one of the solution presenteds that would also work with xs:all.

Upvotes: 2

Related Questions