What I want to validate:
<root xsi:noNamespaceSchemaLocation="test.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<A>
<a id="ID-1"/>
<a id="ID-2"/>
</A>
<BBB>
<b>
<bb>
<bbb idref="ID-1"></bbb>
</bb>
</b>
</BBB>
</root>
Here is my .xsd
file:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:ID"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
However I am getting:
element bbb: Schemas validity error : Element 'bbb', attribute 'idref':
Warning: No precomputed value available, the value was either invalid or something strange happend.
I tried using xsd:NCName
but that didn't change anything. If I use ID-3
which is not yet defined, I get
No match found for key-sequence ['ID-3'] of keyref 'myIdref'.
I want to reference the id
of the A element with idref
of the bbb element. Is my xPath
wrong?
Should I not use xsd:ID
for keyRef
?
I guess that your problem is that you want the bbb
's element attribute type to be xsd:IDREF
rather than xsd:ID
. Then it would correspond with your xsd:ID
definition:
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
A minor fix to add would be adding a maxOccurs="unbounded"
attribute to the
...
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
...
So, the whole XSD could be
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Now your XSD should validate your XML.
To make this work, you don't even need the
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
because this functionality is implied in the xsd:ID
/xsd:IDREF
code. xs:keyref
is more flexible, but in your example, it is not needed.