R – XML Schema – Key in sequence

keyselectoruniquexmlxsd

I'm trying to put a key in sequence and am being bombarded with errors. It seems I can't do this. Additionally, I am being told my key needs a field and selector, which I have been able to find very little documentation on. (In fact, in desperation, I downloaded Liquid XML Studio [vs. Notepad] and searched it's help files. . . to find NO even reference to the word "selector") Regardless – what is another method I can use to guarantee a unique, not null value for an element, within a sequence? (The content in question is a string)

Please note that without the key element, the schema validates.

The error

Invalid per cvc-complex-type.1.2.4:
element {http://www.w3.org/2001/XMLSchema}:key not allowed here (1) in
element {http://www.w3.org/2001/XMLSchema}:sequence, expecting
[{http://www.w3.org/2001/XMLSchema}:annotation, $,
{http://www.w3.org/2001/XMLSchema}:element,
{http://www.w3.org/2001/XMLSchema}:group,
{http://www.w3.org/2001/XMLSchema}:choice,
{http://www.w3.org/2001/XMLSchema}:sequence,
{http://www.w3.org/2001/XMLSchema}:any]:

The schema

<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
 targetNamespace="READOO" elementFormDefault="qualified">

  <xs:element name="ReferralCollection">
    <xs:complexType>
      <xs:sequence>
    <xs:key name="URL" type="string" />
        <xs:element maxOccurs="unbounded" name="keyword">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="occurrences" type="xs:int" use="required" />
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

Best Answer

The key element is not supposed to go inside the sequence element. Instead, you put it as a child of the xs:element that defines ReferralCollection. The selector and field are child elements of the key element that define what is supposed to be unique. Both are XPath expressions. The selector value sets up the XPath context, and the field elements (there can be more than one) define the combination of values that are supposed to be unique. So in your case, the key element might look something like this:

<xs:key name="URL">
  <xs:selector xpath="."/>
  <xs:field xpath="rd:keyword"/>
</xs:key>

The selector here selects the element itself, that is, ReferralCollection. Then, in that context, the field element denotes the values of the keyword elements, which are thus constrained to be unique. The value of an element in XPath is its text content.

I haven't done much with key elements (or XML Schema in general), so some details above might not be correct, but the basic idea is what I explained, so it should be easy to fix any mistakes I made. Oh, also note that I used the rd prefix for your READOO namespace; in my experience using explicit prefixes is always best when dealing with XPath, so you need the appropriate xmlns:rd attribute in your schema to make this work.

EDIT: So it seems you want something like this:

<xs:element name="ReferralCollection">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="URL" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="stem" type="xsd:string"/>
            <xs:element name="keyword" maxOccurs="unbounded">
            ...
            </xs:element>
          ...
  </xs:complexType>

  <xs:key name="URL">
    <xs:selector xpath="./URL"/>
    <xs:field xpath="stem"/>
  </xs:key>
</xs:element>

Is this closer to what you meant? It has URL elements, one or more, each containing a stem element followed by one or more keyword elements. The key constraint should make the contents of the stem elements unique.

Related Topic