Search code examples
xmlxsdxsd-validationunique-constraintxml-validation

xsd:unique constraint on attribute of two different elements


Simple problem: I have two different elements which share the same attribute. How can I achieve uniqueness of this attribute along the two different elements?

Example XML snippet:

<owners>
    <person id="1"/> 
    <company id="2"/>
</owners>

In the above code snippet, I want the id values to be unique along person and company. So that person and company does not have the same id values.


Solution

  • If you're ok with person/@id and company/@id being unique across all elements, simply type those @id attributes as xs:ID.

    If you truly require the scope of uniqueness to be limited to the @ids of those two elements within owners, use xs:unique within owners with a xs:selector/@xpath of person|company:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="owners">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="person" maxOccurs="unbounded">
              <xs:complexType>
                <xs:sequence/>
                <xs:attribute name="id" type="xs:string"/>
              </xs:complexType>
            </xs:element>
            <xs:element name="company" maxOccurs="unbounded">
              <xs:complexType>
                <xs:sequence/>
                <xs:attribute name="id" type="xs:string"/>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
        <xs:unique name="personCompanyIdUniqueness">
          <xs:selector xpath="person|company"/>
          <xs:field xpath="@id"/>
        </xs:unique>
      </xs:element>
    </xs:schema>
    

    If the scope of uniqueness extends to elements higher in your actual hierarchy, raise the xs:unique element and adjust the xs:selector/@xpath accordingly.