XMl Schema: Unique key values within parent

xml, xml-validation, xsd

Solution

I think you've only given a fragment of your xsd? It's easier to debug if you can provide a working snippet. I added a surrounding `<element name="root">` to make it validate.

The problem seems to be that the `enumValueKey` selector groups all of the `enumValues`, across of all the `enumType`'s; but you only want to group those within one `enumType`.

The only way I can see to fix it is to move the `<key>` for `enumValues` into the `enumType` element (and adjust the `xpath` selector), so the whole thing becomes:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="enumTypes">
          <xs:complexType>
            <xs:sequence minOccurs="1" maxOccurs="unbounded">
              <xs:element name="enumType">
                <xs:complexType>
                  <xs:sequence minOccurs="1" maxOccurs="unbounded">
                    <xs:element name="enumValue">
                      <xs:complexType>
                        <xs:attribute name="id" type="xs:string" use="required"/>
                        <xs:attribute name="value" type="xs:string" use="required"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="id" type="xs:string"/>
                </xs:complexType>
                <xs:key name="enumValueKey">
                  <xs:selector xpath="enumValue"/>
                  <xs:field xpath="@id"/>
                </xs:key>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:key name="enumTypeKey">
      <xs:selector xpath="enumTypes/enumType"/>
      <xs:field xpath="@id"/>
    </xs:key>
  </xs:element>
</xs:schema>

This works, in that it allows your XML example, and it forbids the following fragment (with two `1`'s) as it should:

...
<enumType id="2">
  <enumValue id="1" value="Item1"/>
  <enumValue id="1" value="Item2"/>
</enumType>
...

Let me know if this works for you. I'm also interested if there is any other way to express this.

Problem

I have the following XML: ``` <enumTypes xmlns="tempURI"> <enumType id="1"> <enumValue id="1" value="Item1"/> <enumValue id="2" value="Item2"/> <enumValue id="3" value="Item3"/> </enumType> <enumType id="2"> <enumValue id="1" value="Item1"/> <enumValue id="2" value="Item2"/> </enumType> </enumTypes> ``` I also have the following schema: ``` <xs:element name="enumTypes"> <xs:complexType> <xs:sequence minOccurs="1" maxOccurs="unbounded"> <xs:element name="enumType"> <xs:complexType> <xs:sequence minOccurs="1" maxOccurs="unbounded"> <xs:element name="enumValue"> <xs:complexType> <xs:attribute name="id" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:string"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:key name="enumTypeKey"> <xs:selector xpath="enumTypes/enumType"/> <xs:field xpath="@id"/> </xs:key> <xs:key name="enumValueKey"> <xs:selector xpath="enumTypes/enumType/enumValue"/> <xs:field xpath="@id"/> </xs:key> ``` I'm trying to force the enumValue ID's to be unique WITHIN a enumType, but so far I can only get it to force them to be unique across ALL enumTypes. I'm guessing there's a problem with my selector XPath but I can't seem to get it sorted out. Any help would be appreciated!

Original source