Sujal
Sujal

Reputation: 671

How to use key and keyref in XSD?

I have the following XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="library.xsd">
<!--<!DOCTYPE library SYSTEM "library.dtd">-->

<authors>
  <author aid="a1">Bill Evjen</author>
  <author aid="a2">Michael Kay</author>
  <author aid="a3">Kevin Goldberg</author>
  <author aid="a4">Michael Morrison</author>
</authors>

<books>

<book bookID="b001" author="a2">
  <title>XSLT 2.0 and XPath 2.0 Programmer's Reference</title>
  <stock>4</stock>
  <publisher>John Wiley</publisher>
  <year>2009</year>
  <use type="advanced" />
  <use type="reference" />
</book>

<book bookID="b002" author="a1 a2">
  <title>Professional XML (Programmer to Programmer) </title>
  <stock>2</stock>
  <publisher>John Wiley</publisher>
  <year>2007</year>
  <use type="professional" />
  <use type="advanced" />
  <use type="reference" />
</book>

<book bookID="b003" author="a3">
  <title>XML: Visual QuickStart Guide</title>
  <stock>3</stock>
  <publisher>Peachpit Press</publisher>
  <year>2008</year>
  <use type="introductory" />
  <use type="reference" />
</book>

<book bookID="b004" author="a4">
  <title>Sams Teach Yourself XML in 24 Hours</title>
  <stock>5</stock>
  <publisher>SAMS</publisher>
  <year>2005</year>
</book>

</books>

</library>

How do I use key/keyref in xsd so that the 'author' attribute in book element contains value/list of values of 'aid' attribute of author element?

I've tested the following XSD I've created in visual studio but I get the error "The Keyref 'books' cannot find the referred key or unique in scope." and I don't know how to fix this:

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

  <xs:element name="library">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="authors">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="author" maxOccurs="unbounded" type="theAuthor"/>
            </xs:sequence>
          </xs:complexType>
          <xs:key name="uniqueAuthorID">
            <xs:selector xpath="author"/>
            <xs:field xpath="@aid"/>
          </xs:key>

        </xs:element>
        <xs:element name="books">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="book" type="theBook" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:complexType>
          <xs:unique name="uniqueBookID">
            <xs:selector xpath="book"/>
            <xs:field xpath="@bookID"/>
          </xs:unique>
          <xs:keyref refer="uniqueAuthorID" name="authorKeyRef">
            <xs:selector xpath="book"></xs:selector>
            <xs:field xpath="@author"></xs:field>
          </xs:keyref>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>




  <xs:complexType name="theAuthor">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="aid" type="xs:string">
        </xs:attribute>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>



  <xs:complexType name="theBook">
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="stock" type="xs:integer"/>
      <xs:element name="publisher" type="xs:string"/>
      <xs:element name="year" type="xs:string"/>
      <xs:element name="use" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:attribute name="type" type="useType" default="advanced"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="bookID" type="xs:string"/>
    <xs:attribute name="author" type="xs:string"/>
  </xs:complexType>

  <xs:simpleType name="useType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="advanced" />
      <xs:enumeration value="reference" />
      <xs:enumeration value="professional" />
      <xs:enumeration value="introductory" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

Upvotes: 3

Views: 8261

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21638

The problem is in the layout/scope of your constraint declarations. Let's have a look at the diagram below:

enter image description here

Just like in a "curly brackets" programming world (Java/C#), your elements act as a "block" that automatically scopes the name of declarations. In this case, your uniqueAuthorID is visible to authors and below, which is why is not visible to what's defined under books.

So what you need to do is move and amend the uniqueAuthorID under library.

enter image description here

This should take care of your XSD issues.

Your XML will not validate though as you're expecting:

The key sequence 'a1 a2' in Keyref fails to refer to some key.

Even if you would have properly define the author as a list constrained simple type, the keyref mechanism doesn't break it in its component values. To make it work, you would have to convert the author attribute to repeating elements, and kave the keyref check it for each element instead (just in case, attributes cannot repeat).

Upvotes: 6

Related Questions