kinimod
kinimod

Reputation: 44

XSD <xs:key> separate uniqueness constraints for different elements?

I'm fairly new to XSD validation so there might be something crucial that I am missing, but I've looked around quite a bit and can't seem to find an appropriate solution.

What I'm trying to do is something like this:

Consider this XML example, I'm forced to use (simplified)

.
.
.

<categories>
      <orange id="1" value="10">...</orange>
      <orange id="2" value="10">...</orange>
      <brown id="1" value="10">...</brown>
      <brown id="2" value="10">...</brown>
      <brown id="3" value="10">...</brown>
      .
      .
      .
</categories>

Basically I want to ensure that the id is unique for all orange categories and brown categories but not unique overall.

My initial XSD would look something like this:

.
.
.
<xs:element name="categories">
 <xs:complexType>
  <xs:choice maxOccurs="unbounded">
   <xs:element name="orange">
     <xs:complexType>
      <xs:attribute name="id" type="xs:integer" use="required"/>
      <xs:attribute name="value" type="xs:integer" use="required"/>
     </xs:complexType>
    </xs:element>
    <xs:element name="brown ">
     <xs:complexType>
      <xs:attribute name="id" type="xs:integer" use="required"/>
      <xs:attribute name="value" type="xs:integer" use="required"/>
     </xs:complexType>
    </xs:element>
   </xs:choice>
 </xs:complexType> 

 <xs:key name="catKeys">
  <xs:selector xpath="/*" />
  <xs:field    xpath="@id" />
 </xs:key>

</xs:element>

Above XSD checks the id-uniqueness across all categories -> The XML won't validate.

Upvotes: 2

Views: 204

Answers (1)

kjhughes
kjhughes

Reputation: 111726

You're very close. Simply use two xs:key elements, one for each of orange and brown:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="categories">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="orange">
          <xs:complexType>
            <xs:attribute name="id" type="xs:integer" use="required"/>
            <xs:attribute name="value" type="xs:integer" use="required"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="brown ">
          <xs:complexType>
            <xs:attribute name="id" type="xs:integer" use="required"/>
            <xs:attribute name="value" type="xs:integer" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType> 

    <xs:key name="orangeKeys">
      <xs:selector xpath="orange"/>
      <xs:field    xpath="@id"/>
    </xs:key>

    <xs:key name="brownKeys">
      <xs:selector xpath="brown"/>
      <xs:field    xpath="@id"/>
    </xs:key>
  </xs:element>

</xs:schema>

Then your XML will be valid, given that it has unique id elements with scopes separate for orange vs brown elements.

Upvotes: 2

Related Questions