XSD key/keyref beginner question

keyref, schema, xml, xsd

Solution

Your XML document, as shown, doesn't include a schemaLocation. When an XML document doesn't reference a schema or DTD, it may pass validation simply by being well-formed XML. (This once happened to a co-worker, using a different validator. I think it's a bug that the validator didn't at least give a warning that it was missing a schema or DTD. But I digress.)

Anyway, it should probably be something like:

<?xml version="1.0"?>
<foo
  xmlns="test" <!-- This is bad form, by the way... -->
  xsi:schemaLocation="test /path/to/schema/document"
    <bar id="1" />
    <bar id="2" />
    <batz idref="1" /> <!-- this should succeed because <bar id="1"> exists -->
    <batz idref="3" /> <!-- this should FAIL -->
</foo>

Problem

I'm trying to implement a very simple XML schema constraint. The idref attribute on elements of type <batz> should only be allowed to have a value that matches the id attribute on at least one element <bar>. If that doesn't make any sense to you then please just look at the example XML-document below, I think it actually explains it better than my attempt to put it in words. So, question: Why does xmllint let the below schema/xml combination pass (it says the document is valid)? How to fix it to achieve the desired constraint? The schema: ``` <?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="test" xmlns="test" elementFormDefault="qualified"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="id" use="required" type="xs:string" /> </xs:complexType> </xs:element> <xs:element name="batz" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="idref" use="required" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:key name="ID"> <xs:selector xpath="./bar" /> <xs:field xpath="@id" /> </xs:key> <xs:keyref name="IDREF" refer="ID"> <xs:selector xpath="./batz" /> <xs:field xpath="@idref" /> </xs:keyref> </xs:element> </xs:schema> ``` The document: ``` <?xml version="1.0"?> <foo xmlns="test"> <bar id="1" /> <bar id="2" /> <batz idref="1" /> <!-- this should succeed because <bar id="1"> exists --> <batz idref="3" /> <!-- this should FAIL --> </foo> ```

Original source

Related problems