Xml Schema substitution groups / key keyref

Discussion in 'XML' started by John Carron, Sep 1, 2005.

  1. John Carron

    John Carron Guest

    Hi All,

    I have written a simple schema (see below) that uses substitution
    groups. I don't know if this the correct usage because I'm fairly new to
    xml schema.

    The structure is as follows:

    Request
    Report
    TargetReference (reference identifier attribute)
    Target (identifier attribute)

    Example Document:

    <?xml version="1.0" encoding="UTF-8"?>
    <Request xmlns="urn:demo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:demo
    Untitled23.xsd">
    <DummyReport identifier="10">
    <TargetReference identifier="20"/>
    </DummyReport>
    <DummyTarget identifier="20"/>
    </Request>

    A valid document can contain a number of reports and targets. The target
    reference element should reference only targets in the document and I would
    like to enforce this. Does anybody know how to do this? I was initially
    thinking along the lines of using the Key and KeyRef elements but don't know
    how to do that with substitution groups? Is it possible? I would also like
    to enforce that all target identifier attributes are unique. Can this be
    done?

    Any help would be appreciated.

    Regards

    Darren

    2) Send newsgroup message:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns="urn:demo" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="urn:demo" elementFormDefault="qualified"
    attributeFormDefault="unqualified">

    <!-- Root element request -->
    <xs:element name="Request">
    <xs:complexType>
    <xs:sequence>
    <xs:element ref="ReportGroup"
    maxOccurs="unbounded"/>
    <xs:element ref="TargetGroup"
    maxOccurs="unbounded"/>
    </xs:sequence>
    </xs:complexType>
    </xs:element>

    <!-- Abstract report type -->
    <xs:complexType name="Report" abstract="true">
    <xs:sequence>
    <xs:element ref="TargetReference"
    maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="identifier" type="xs:int"
    use="required"/>
    </xs:complexType>

    <!-- Abstract target type -->
    <xs:complexType name="Target" abstract="true">
    <xs:attribute name="identifier" type="xs:int"
    use="required"/>
    </xs:complexType>
    <xs:element name="ReportGroup" type="Report" abstract="true"/>
    <xs:element name="TargetGroup" type="Target" abstract="true"/>

    <!-- Element to join a report to a target -->
    <xs:element name="TargetReference">
    <xs:complexType>
    <xs:attribute name="identifier" type="xs:int"
    use="required"/>
    </xs:complexType>
    </xs:element>

    <!-- Reports -->
    <xs:element name="DummyReport" substitutionGroup="ReportGroup">
    <xs:complexType>
    <xs:complexContent>
    <xs:extension base="Report"/>
    </xs:complexContent>
    </xs:complexType>
    </xs:element>
    <xs:element name="AnotherDummyReport"
    substitutionGroup="ReportGroup">
    <xs:complexType>
    <xs:complexContent>
    <xs:extension base="Report"/>
    </xs:complexContent>
    </xs:complexType>
    </xs:element>

    <!-- Targets -->
    <xs:element name="DummyTarget" substitutionGroup="TargetGroup">
    <xs:complexType>
    <xs:complexContent>
    <xs:extension base="Target"/>
    </xs:complexContent>
    </xs:complexType>
    </xs:element>
    <xs:element name="DummyTarget2" substitutionGroup="TargetGroup">
    <xs:complexType>
    <xs:complexContent>
    <xs:extension base="Target"/>
    </xs:complexContent>
    </xs:complexType>
    </xs:element>

    </xs:schema>
     
    John Carron, Sep 1, 2005
    #1
    1. Advertising

  2. Hi,

    If you want the identifiers to be unique across all reports and targets,
    you can add this to your declaration of the Request element:

    <xs:key name="uniqueIDs">
    <xs:selector xpath="*"/>
    <xs:field xpath="@identifier"/>
    </xs:key>

    If you only want the identifiers to be unique among targets (and not
    reports) and you know all the target element names in advance, you could
    use:

    <xs:key name="uniqueIDs">
    <xs:selector xpath="demo:DummyTarget|demo:DummyTarget2"/>
    <xs:field xpath="@identifier"/>
    </xs:key>

    But, if you only want the identifiers to be unique among targets, and
    you don't want to hard code the names in there, I think you'd have to
    use a different attribute name for target IDs vs. report IDs.

    To enforce the reference, you can use:

    <xs:keyref name="validRefs" refer="uniqueIDs">
    <xs:selector xpath=".//demo:TargetReference"/>
    <xs:field xpath="@identifier"/>
    </xs:keyref>

    Note that I use a "demo" prefix - You would have to map your target
    namespace to a prefix in your schema in order for this to work, because
    XPath expressions do not take into account default namespace
    declarations.

    Hope that helps,
    Priscilla

    ----------------------------------
    Priscilla Walmsley
    Author, Definitive XML Schema
    http://www.datypic.com
    ----------------------------------

    *** Sent via Developersdex http://www.developersdex.com ***
     
    Priscilla Walmsley, Sep 2, 2005
    #2
    1. Advertising

  3. John Carron

    John Carron Guest

    Hi Priscilla ,

    Many thanks for the reply. It worked a treat.

    Thanks again

    Darren

    "Priscilla Walmsley" <> wrote in message
    news:TaYRe.3$...
    > Hi,
    >
    > If you want the identifiers to be unique across all reports and targets,
    > you can add this to your declaration of the Request element:
    >
    > <xs:key name="uniqueIDs">
    > <xs:selector xpath="*"/>
    > <xs:field xpath="@identifier"/>
    > </xs:key>
    >
    > If you only want the identifiers to be unique among targets (and not
    > reports) and you know all the target element names in advance, you could
    > use:
    >
    > <xs:key name="uniqueIDs">
    > <xs:selector xpath="demo:DummyTarget|demo:DummyTarget2"/>
    > <xs:field xpath="@identifier"/>
    > </xs:key>
    >
    > But, if you only want the identifiers to be unique among targets, and
    > you don't want to hard code the names in there, I think you'd have to
    > use a different attribute name for target IDs vs. report IDs.
    >
    > To enforce the reference, you can use:
    >
    > <xs:keyref name="validRefs" refer="uniqueIDs">
    > <xs:selector xpath=".//demo:TargetReference"/>
    > <xs:field xpath="@identifier"/>
    > </xs:keyref>
    >
    > Note that I use a "demo" prefix - You would have to map your target
    > namespace to a prefix in your schema in order for this to work, because
    > XPath expressions do not take into account default namespace
    > declarations.
    >
    > Hope that helps,
    > Priscilla
    >
    > ----------------------------------
    > Priscilla Walmsley
    > Author, Definitive XML Schema
    > http://www.datypic.com
    > ----------------------------------
    >
    > *** Sent via Developersdex http://www.developersdex.com ***
     
    John Carron, Sep 2, 2005
    #3
    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:
    530
    Mark Preston
    Aug 19, 2003
  2. peterpeter
    Replies:
    0
    Views:
    953
    peterpeter
    Feb 11, 2004
  3. John Carron
    Replies:
    0
    Views:
    499
    John Carron
    Sep 1, 2005
  4. Jaunedeau
    Replies:
    2
    Views:
    410
    Henry S. Thompson
    Sep 30, 2005
  5. Soren Kuula
    Replies:
    2
    Views:
    588
    Soren Kuula
    Feb 3, 2006
Loading...

Share This Page