XMLSchema: key/keyref

Discussion in 'XML' started by Roland Praehofer, Feb 15, 2006.

  1. 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.
    --
    Roland Prähofer
     
    Roland Praehofer, Feb 15, 2006
    #1
    1. Advertising

  2. Roland Praehofer

    George Bina Guest

    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
    ---------------------------------------------------------------------
    George Cristian Bina
    <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
    http://www.oxygenxml.com
     
    George Bina, Feb 16, 2006
    #2
    1. Advertising

  3. 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>
    </c>


    > 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
    > ---------------------------------------------------------------------
    > George Cristian Bina
    > <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
    > http://www.oxygenxml.com


    --
    memeticdesign
    Roland Praehofer
    T: 030 827 029 77
    E:
    W: www.memeticdesign.de
     
    Roland Praehofer, Feb 16, 2006
    #3
  4. Roland Praehofer

    George Bina Guest

    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
    ---------------------------------------------------------------------
    George Cristian Bina
    <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
    http://www.oxygenxml.com
     
    George Bina, Feb 16, 2006
    #4
  5. 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
    > ---------------------------------------------------------------------
    > George Cristian Bina
    > <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
    > http://www.oxygenxml.com


    --
    memeticdesign
    Roland Praehofer
    T: +49 030 827 029 77
    E:
    W: www.memeticdesign.de
     
    Roland Praehofer, Feb 16, 2006
    #5
  6. Roland Praehofer writes:

    > 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:
    URL: http://www.ltg.ed.ac.uk/~ht/
    [mail really from me _always_ has this .sig -- mail without it is forged spam]
     
    Henry S. Thompson, Feb 20, 2006
    #6
  7. Roland Praehofer

    George Bina Guest

    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
    ---------------------------------------------------------------------
    George Cristian Bina
    <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
    http://www.oxygenxml.com
     
    George Bina, Feb 21, 2006
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marek Malowidzki

    Key/keyref validation in schema?

    Marek Malowidzki, Aug 18, 2003, in forum: XML
    Replies:
    1
    Views:
    513
    Mark Preston
    Aug 19, 2003
  2. J E E
    Replies:
    0
    Views:
    381
    J E E
    Nov 7, 2003
  3. peterpeter
    Replies:
    0
    Views:
    931
    peterpeter
    Feb 11, 2004
  4. Markus Seibold

    <key><keyref> does not work in XMLSpy

    Markus Seibold, Feb 13, 2004, in forum: XML
    Replies:
    0
    Views:
    1,314
    Markus Seibold
    Feb 13, 2004
  5. Russell O'Connor

    Key-keyref to attribute in root element

    Russell O'Connor, Mar 5, 2004, in forum: XML
    Replies:
    5
    Views:
    991
    Henry S. Thompson
    Apr 27, 2004
Loading...

Share This Page