title: XSD key/keyref: hierarchical key structure
body: <p>I'm trying to define some foreign key constraints on an XML schema using xs:key and xs:keyref definitions. I want the structure of the document to be hierarchical in the following way:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;tns:root xmlns:tns="http://www.example.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/ SampleSchema.xsd "&gt;
    &lt;parent parentKey="parent1"&gt;
      &lt;child childKey="child1"/&gt;
      &lt;child childKey="child2"/&gt;
    &lt;/parent&gt;
    &lt;parent parentKey="parent2"&gt;
      &lt;child childKey="child1"/&gt;
      &lt;child childKey="child2"/&gt;
    &lt;/parent&gt;
    &lt;referrer parentRef="parent1" childRef="child2"/&gt;
  &lt;/tns:root&gt;
  </code></pre>
  
  <p>A each parent has a (globally) unique key, defined by parentKey. Each child has key defined by childKey, <em>but childKey is only unique within the scope of its containing parent</em>.</p>
  
  <p>There is then a list of referrers with foreign key references to a particular parent and child.</p>
  
  <p>I'm able to define the keys as I want, simply by putting them on the correct element: the parentKey constraint on the root element, and the childKey constraint on the parent element. I can also define the keyref to parentKey without difficulty.</p>
  
  <p>The problems arise when trying to define a keyref to childKey. I tried defining a simple keyref on the root element to childKey, but that doesn't work since I see no way to select only the child elements under the proper parent subtree. (The Eclipse validator, at least, always simply validates against the content of the <em>last</em> parent subtree in the document...).</p>
  
  <p>I then tried defining a composite key (on root), with:</p>
  
  <ul>
  <li>selector = parent</li>
  <li>field = @parentKey</li>
  <li>field = child/@childKey</li>
  </ul>
  
  <p>This fails if there is more than one child defined under the parent. That is the correct behavior based on the <a href="http://www.w3.org/TR/xmlschema11-1/" rel="noreferrer">XSD 1.1 spec</a>, section 3.11.4, item 3, which states that the key has to match at most one node per field definition.</p>
  
  <p>Just to reiterate: if I force childKeys to be globally unique, this is easy to implement; the difficulty is around referencing <em>locally</em> unique childKeys.</p>
  
  <p>Any XSD masters out there have an idea?</p>
  
  <p>For reference, here is a sample XSD, with a failed childKey keyref commented out:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/" xmlns:tns="http://www.example.org/" elementFormDefault="unqualified"&gt;
  
      &lt;element name="root"&gt;
          &lt;complexType&gt;
              &lt;sequence&gt;
                  &lt;element name="parent" maxOccurs="unbounded" minOccurs="1"&gt;
                      &lt;complexType&gt;
                          &lt;sequence&gt;
                              &lt;element name="child" maxOccurs="unbounded" minOccurs="1"&gt;
                                  &lt;complexType&gt;
                                      &lt;attribute name="childKey" type="string" use="required"/&gt;
                                  &lt;/complexType&gt;
                              &lt;/element&gt;
                          &lt;/sequence&gt;
                          &lt;attribute name="parentKey" type="string" use="required"/&gt;
                      &lt;/complexType&gt;
                      &lt;key name="childKeyDef"&gt;
                          &lt;selector xpath="child"/&gt;
                          &lt;field xpath="@childKey"/&gt;
                      &lt;/key&gt;
                  &lt;/element&gt;
                  &lt;element name="referrer" maxOccurs="unbounded" minOccurs="1"&gt;
                      &lt;complexType&gt;
                          &lt;attribute name="parentRef" type="string"/&gt;
                          &lt;attribute name="childRef" type="string"/&gt;
                      &lt;/complexType&gt;
                  &lt;/element&gt;
              &lt;/sequence&gt;
          &lt;/complexType&gt;
          &lt;key name="parentKeyDef"&gt;
              &lt;selector xpath="parent"/&gt;
              &lt;field xpath="@parentKey"/&gt;
          &lt;/key&gt;
          &lt;keyref name="parentKeyRef" refer="tns:parentKeyDef"&gt;
              &lt;selector xpath="referrers"/&gt;
              &lt;field xpath="@parentRef"/&gt;
          &lt;/keyref&gt;
  &lt;!--        &lt;keyref name="childKeyRef" refer="tns:childKeyDef"&gt;--&gt;
  &lt;!--            &lt;selector xpath="referrers"/&gt;--&gt;
  &lt;!--            &lt;field xpath="@childRef"/&gt;--&gt;
  &lt;!--        &lt;/keyref&gt;--&gt;
      &lt;/element&gt;
  &lt;/schema&gt;
  </code></pre>