ssalbdivad
ssalbdivad

Reputation: 26

Can an XSD file ensure that an attribute of an element that occurs an unbounded number of times is true exactly once?

The XML I'm structuring can contain any number of "user" elements, and I want to ensure that an attribute called "isDefault" is set to true on exactly one of those users.

For example, something like this would be valid:

<users>
    <user isDefault="false"/>
    <user isDefault="true"/>
    <user isDefault="false"/>
</users>

However, this:

<users>
    <user isDefault="true"/>
    <user isDefault="true"/>
    <user isDefault="false"/>
</users>

And this:

<users>
    <user isDefault="false"/>
    <user isDefault="false"/>
    <user isDefault="false"/>
</users>

Would be invalid. Can I achieve this using an XSD or do I need to validate it programmatically?

Upvotes: 1

Views: 68

Answers (2)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25034

One simple way to solve this problem is to re-think the XML and specify that the default user is listed first, and the user listed first is the default user. Then a change to the default user involves moving that user to the top of the list, instead of changing two isDefault values, and you are guaranteed without any further effort that there is always exactly one user element which is first.

Upvotes: 1

helderdarocha
helderdarocha

Reputation: 23637

If the isDefault attribute has to always be present, you can't achieve this with XSD 1.0 alone.

With XSD 1.1 you could use an <xs:assert>:

<xs:element name="users">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="user" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:assert test="count(user[@isDefault='true']) = 1"/>
    </xs:complexType>
</xs:element>

Upvotes: 0

Related Questions