I am trying to determine how to modify my XSD to utilize an enumeration in two places in XML but with different data types. I’m using Visual Studio 2010 as my XML editor.
Imagine an XML doc that contains both types of vehicles and orders for said vehicles. Rules are as follows:
- Each vehicle must have a unique attribute – model – so attribute
should be of type xs:ID. - Each order can have multiple vehicles, so
model attribute should be of type xs:string or the like.
Here is my XML file — Test.xml
<?xml version="1.0" encoding="utf-8" ?>
<sample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Test.xsd">
<vehicles>
<vehicle model="Equinox" />
<vehicle model="Impala"/>
<!-- This should not be allowed because it's not unique -->
<vehicle model="Impala" />
<!-- This should not be allowed because it is not a valid model -->
<vehicle model="Apple" />
</vehicles>
<orders>
<order orderid="123">
<item quantity="3" model="Equinox" />
<item quantity="2" model="Impala" />
<item quantity="3" model="Impala" />
</order>
</orders>
</sample>
Here is my XSD file – Test.xsd (in same location as XML)
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sample">
<xs:complexType>
<xs:sequence>
<xs:element name="vehicles">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="vehicle">
<xs:complexType>
<!-- this instance of model should be unique -->
<xs:attribute name="model" type="UniqueModel" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="orders">
<xs:complexType>
<xs:sequence>
<xs:element name="order">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="quantity" type="xs:unsignedByte" use="required" />
<!-- this instance of model can be repeated -->
<xs:attribute name="model" type="ModelList" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="orderid" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="UniqueModel">
<xs:restriction base="xs:ID">
<!-- I want to import ModelList here-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ModelList">
<xs:union memberTypes="ChevyModelList DodgeModelList" />
</xs:simpleType>
<xs:simpleType name="ChevyModelList">
<xs:restriction base="xs:normalizedString">
<xs:enumeration value="Equinox" />
<xs:enumeration value="Impala" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="DodgeModelList">
<xs:restriction base="xs:normalizedString">
<xs:enumeration value="Charger" />
<xs:enumeration value="Ram" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
I’ve done many Google and Stack Overflow searches trying to determine if this is possible but couldn’t find anything relevant.
Perhaps I need to go back to my original thoughts — which was to restrict the data using xs:unique. I can’t get this to work, either:
<xs:element name="vehicles">
<!-- vehicle complexType here -->
<xs:unique name="uniqueModel">
<xs:selector xpath="vechicle" />
<xs:field xpath="@model" />
</xs:unique>
</xs:element>
Any help on getting either solution to work would be awesome!
Thanks!
Thad
The
xs:IDtype means more than just uniqueness, it also restricts the value to be a valid XML name, which in particular means no spaces and not starting with a number (you couldn’t have, for example, a Peugeot model named “307”). I’d probably approach the problem by using a keyand make the
vehicleelement’smodelattribute be of typeModelList. Thekeyshould ensure that the model names withinvehiclesare unique, and thekeyRefchecks that the model mentioned in each order item is in fact one of those listed undervehicles. That way you don’t actually need to restrict the type of theitem/@modelattribute at all, it could just be a plainxs:stringas thekeyRefwill enforce the enumeration for you.