Doing More With XML Schemas (part 3) - Two For One
(Page 6 of 6 )
Now, how about letting me twist your mind a little further? In the example on the previous page, I stated that there could only be one entry for each ship in the fleet. Let's now modify that statement a little and permit repetitions, so long as the the combination of ship name and droid code is unique.
The following XML document sample might make this clearer:
<?xml version="1.0" encoding="UTF-8"?>
<fleet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ship
name="Jabitha">
<droid type="R2D2">2</droid>
</ship>
<ship name="Jabitha">
<droid
type="C3P0">5</droid>
</ship>
<ship name="Millennium Falcon">
<droid
type="C3PO">4</droid>
</ship>
<droids>
<droid type="R2D2">astromech
droid</droid>
<droid type="C3PO">protocol droid</droid>
<droid
type="CZ-3">humanoid droid</droid>
<droid type="LE-BO2D9">repair droid</droid>
</droids>
</fleet>
As you can see above, my document includes more than one entry for a particular
ship name. However, the combination of ship and droid is unique. In order to ensure that this rule is followed consistently, I need to update my schema definition to use what is known as a "unique composed value". A unique composed value specifies uniqueness of an element by using two (or more) parameters.
Next question: how do you defined a unique composed value?
Take a look:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element
name="fleet">
<xsd:complexType>
<xsd:sequence>
<xsd:element
name="ship" type="shipType"
minOccurs="0" maxOccurs="unbounded"/>
<xsd:element
name="droids"
type="droidsGroupType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:unique
name="NoDuplicates">
<xsd:selector xpath="ship"/>
<xsd:field xpath="@name"/>
<xsd:field
xpath="droid/@type"/>
</xsd:unique>
</xsd:element>
<xsd:complexType
name="droidType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute
name="type"
type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType
name="shipType">
<xsd:sequence>
<xsd:element name="droid" type="droidType"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType
name="droidsGroupType">
<xsd:sequence>
<xsd:element name="droid" type="droidType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
It's pretty simple - all I've done is add an additional field to the <xsd:unique>
element, in order to ensure that only the combined set of ship name and droid type is unique. You don't have to stop there either - a unique composed value may be made up of as many components as you like.
How do I know that this actually works? Create a duplicate entry in the XML document above, validate the file, and see what happens. Your XML validator should start complaining bitterly about uniqueness constraint violations.
And that's about it for the moment. In this article, I introduced you to the concept of uniqueness in the XML Schema world, showing you how to use built-in schema constructs to enforce uniqueness within your XML document instances. I also showed you how you could replicate RDBMS referential integrity constraints within the context of an XML document, using schema equivalents of primary and foreign keys, and creating relationships between the different nodes of an XML document. All these techniques come in handy to reduce errors when you're building schema definitions which contain internal inter-relationships that need to be rigidly enforced across document instances.
In the next (and final) article in this series, I'll be wrapping up this discussion of advanced schema theory with an overview of XML namespaces, and how they fit into the XML Schema picture. Make sure you come back for that one!
Note: All examples in this article have been tested on Linux/i586. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |