XMLSchema: key/keyref

R

Roland Praehofer

Hi!

I'm trying to accomplish the following:

<root xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='teaser.xsd'>

<b>
<a>John</a>
<a>Paul/a>
<a>George</a>
<a>Ringo/a>
<b>

<c>
<a>John</a>
<a>Paul</a>
<a>Ringo</a>
</c>

<c>
<a>John</a>
<a>Paul</a>
<a>George</a>
</c>

</root>

I want to make sure not only, that every c/a is equal to one of b/a.
(I can make c/a/. the keyref of b/a)
But also every b/a should be present in every c/a.

To simplify it:
Every c/a/. should have an correspondent b/a/.

Any help would be appreciated.
Thanks.
 
G

George Bina

Hi,

If b/a values are unique then you can define that as a key and the c/a
values as key references. If they are not unique then you cannot do
that with XML Schema alone but you can solve that with XML Schema and
embedded Schematron rules.

Here it is a sample schema for the first case when b/a values are
unique:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="b"/>
<xs:element maxOccurs="unbounded" ref="c"/>
</xs:sequence>
</xs:complexType>
<xs:key name="aOfb">
<xs:selector xpath="b/a"/>
<xs:field xpath="."/>
</xs:key>
<xs:keyref refer="aOfb" name="aOfc">
<xs:selector xpath="c/a"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:element name="b">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a" type="xs:NCName"/>
</xs:schema>

Best Regards,
George
 
R

Roland Praehofer

Hi George!

Thanks for your reply!

As I wrote, there's no problem in making c/a a keyref for b/a.
Also b/a values _are_ unique.

I have to make sure though, that _all_ b/a's are also in c/a,
which is not guarranteed here.

All the Best,

Roland

-----------

<b>
<a>John</a>
<a>Paul/a>
<a>George</a>
<a>Ringo/a>
<b>

<c>
<a>John</a>
<a>Paul</a>
<a>Ringo</a>
</c>

<c>
<a>John</a>
<a>Paul</a>
<a>George</a>
Hi,

If b/a values are unique then you can define that as a key and the c/a
values as key references. If they are not unique then you cannot do
that with XML Schema alone but you can solve that with XML Schema and
embedded Schematron rules.

Here it is a sample schema for the first case when b/a values are
unique:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="b"/>
<xs:element maxOccurs="unbounded" ref="c"/>
</xs:sequence>
</xs:complexType>
<xs:key name="aOfb">
<xs:selector xpath="b/a"/>
<xs:field xpath="."/>
</xs:key>
<xs:keyref refer="aOfb" name="aOfc">
<xs:selector xpath="c/a"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:element name="b">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a" type="xs:NCName"/>
</xs:schema>

Best Regards,
George

--
memeticdesign
Roland Praehofer
T: 030 827 029 77
E: (e-mail address removed)
W: www.memeticdesign.de
 
G

George Bina

Hi Roland,

Then you will need Schematron to test that for an b/a there is at least
a c/a with the same value. Here it is a complete working schema that
does that:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="b"/>
<xs:element maxOccurs="unbounded" ref="c"/>
</xs:sequence>
</xs:complexType>
<xs:key name="aOfb">
<xs:selector xpath="b/a"/>
<xs:field xpath="."/>
</xs:key>
<xs:keyref refer="aOfb" name="aOfc">
<xs:selector xpath="c/a"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:element name="b">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a" type="xs:NCName">
<xs:annotation>
<xs:appinfo>
<sch:pattern name="Check that b/a has a c/a with the same
value.">
<sch:rule context="a[parent::b]">
<sch:assert test=".=../../c/a">There is no c/a with the
same value.</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:schema>

On the following document

<root>

<b>
<a>John</a>
<a>Paul</a>
<a>George</a>
<a>Ringo</a>
<a>NotHere</a>
</b>

<c>
<a>John</a>
<a>Paul</a>
<a>Ringo</a>
</c>

<c>
<a>John</a>
<a>Paul</a>
<a>George</a>
</c>

</root>

I get:

SystemID: C:\george\workspace\oXygen\samples\test.xml
Location: 8:0
Description: There is no c/a with the same value. (.=../../c/a)
where line 8 is <a>NotHere</a>

Best Regards,
George
 
R

Roland Praehofer

Hi George !

Thanks a lot!
Never used Schematron before, so some work has to be done.
It looks like it's the solution for my problem, though.

Thanks,

Roland
Hi Roland,

Then you will need Schematron to test that for an b/a there is at least
a c/a with the same value. Here it is a complete working schema that
does that:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="b"/>
<xs:element maxOccurs="unbounded" ref="c"/>
</xs:sequence>
</xs:complexType>
<xs:key name="aOfb">
<xs:selector xpath="b/a"/>
<xs:field xpath="."/>
</xs:key>
<xs:keyref refer="aOfb" name="aOfc">
<xs:selector xpath="c/a"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:element name="b">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="a"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a" type="xs:NCName">
<xs:annotation>
<xs:appinfo>
<sch:pattern name="Check that b/a has a c/a with the same
value.">
<sch:rule context="a[parent::b]">
<sch:assert test=".=../../c/a">There is no c/a with the
same value.</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:schema>

On the following document

<root>

<b>
<a>John</a>
<a>Paul</a>
<a>George</a>
<a>Ringo</a>
<a>NotHere</a>
</b>

<c>
<a>John</a>
<a>Paul</a>
<a>Ringo</a>
</c>

<c>
<a>John</a>
<a>Paul</a>
<a>George</a>
</c>

</root>

I get:

SystemID: C:\george\workspace\oXygen\samples\test.xml
Location: 8:0
Description: There is no c/a with the same value. (.=../../c/a)
where line 8 is <a>NotHere</a>

Best Regards,
George

--
memeticdesign
Roland Praehofer
T: +49 030 827 029 77
E: (e-mail address removed)
W: www.memeticdesign.de
 
H

Henry S. Thompson

Roland said:
Hi George!

Thanks for your reply!

As I wrote, there's no problem in making c/a a keyref for b/a.
Also b/a values _are_ unique.

I have to make sure though, that _all_ b/a's are also in c/a,
which is not guarranteed here.

So make b/a a keyref as well, to c/a as a key. This forces the two to
be identical ignoring order.

ht
--
Henry S. Thompson, HCRC Language Technology Group, University of Edinburgh
Half-time member of W3C Team
2 Buccleuch Place, Edinburgh EH8 9LW, SCOTLAND -- (44) 131 650-4440
Fax: (44) 131 650-4587, e-mail: (e-mail address removed)
URL: http://www.ltg.ed.ac.uk/~ht/
[mail really from me _always_ has this .sig -- mail without it is forged spam]
 
G

George Bina

Hello Henry,

The problem as I understand from the OP example is that c/a values are
not unique, so they cannot form a key.

Best Regards,
George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,001
Messages
2,570,255
Members
46,852
Latest member
CarlaDowle

Latest Threads

Top