Search code examples
xmlxsdattributesschematron

XML Schema - Only one of elements can have an attribute


I have a struggle with XSD schema. I want to put a restriction where only one of the element within a node can have the cetrain arttribute and don't affect the other one.

Giving you an example of valid and invalid XML files would be better:

Valid XML

The tag someone must contain the attriubte @id, but the only one of them would be honored to have the @status attribute with the captain value.

<node>
    <someone id="01">Alex</someone>
    <someone id="02">Amanda</someone>
    <someone id="03" status="captain">Bob</someone>
    <someone id="04">Costa</someone>
</node>

Invalid XML

The following ones are invalid. There is no way to have two ones with @status.

<node>
    <someone id="01" status="captain">Alex</someone>
    <someone id="02">Amanda</someone>
    <someone id="03" status="captain">Bob</someone>
    <someone id="04">Costa</someone>
</node>

And also not possible to skip the @id.

<node>
    <someone status="captain">Alex</someone>
    <someone id="01">Amanda</someone>
    <someone id="02">Costa</someone>
</node>

My actual XSD

I have the following piece of xsd file so far, however I have no idea how to apply the restriction described above.

<xsd:complexType name="nodeType">
    <xsd:sequence>
        <xsd:element name="someone" type="xsd:string"/>
    </xsd:sequence>
    <xsd:attribute name="id" type="idType" use="required"/>
</xsd:complexType>

I am thankful for the help. I think the way using would do the work better and easier, however I have a really little experience with that.


Solution

  • Can't be done with XSD 1.0. Very easy to do with XSD 1.1 using assertions. Not sure I understand the condition exactly, but it's something

    <xs:assert test="count(*/@status)=1"/>