Reputation: 1354
I would like to define an xsd schema which contains an enumeration. The enumeration's value should however be exclusive across the entire document. To illustrate this, consider the following schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="urn:enumtest" targetNamespace="urn:enumtest" elementFormDefault="qualified">
<xs:simpleType name="Country">
<xs:restriction base="xs:string">
<xs:enumeration value="CH"/>
<xs:enumeration value="AT"/>
<xs:enumeration value="DE"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Address">
<xs:sequence>
<xs:element name="Street" type="xs:string"/>
<xs:element name="No" type="xs:integer"/>
<xs:element name="Code" type="xs:integer"/>
<xs:element name="Country" type="Country"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Items">
<xs:sequence>
<xs:element name="Address" type="Address" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:element name="Items" type="Items"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The following two documents should pass validation because they each contain a unique value from the Country
enumeration across the document (CH in first document, AT in second document):
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:enumtest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:enumtest enumtest.xsd">
<Items>
<Address>
<Street>Street1</Street>
<No>1</No>
<Code>1</Code>
<Country>CH</Country>
</Address>
<Address>
<Street>Street2</Street>
<No>2</No>
<Code>2</Code>
<Country>CH</Country>
</Address>
<Address>
<Street>Street3</Street>
<No>3</No>
<Code>3</Code>
<Country>CH</Country>
</Address>
</Items>
</Document>
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:enumtest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:enumtest enumtest.xsd">
<Items>
<Address>
<Street>Street1</Street>
<No>1</No>
<Code>1</Code>
<Country>AT</Country>
</Address>
<Address>
<Street>Street2</Street>
<No>2</No>
<Code>2</Code>
<Country>AT</Country>
</Address>
<Address>
<Street>Street3</Street>
<No>3</No>
<Code>3</Code>
<Country>AT</Country>
</Address>
</Items>
</Document>
The next document should be flagged as invalid since there is more than one value from the Country
enumeration present in the document (CH and DE):
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:enumtest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:enumtest enumtest.xsd">
<Items>
<Address>
<Street>Street1</Street>
<No>1</No>
<Code>1</Code>
<Country>CH</Country>
</Address>
<Address>
<Street>Street2</Street>
<No>2</No>
<Code>2</Code>
<Country>CH</Country>
</Address>
<Address>
<Street>Street3</Street>
<No>3</No>
<Code>3</Code>
<Country>DE</Country>
</Address>
</Items>
</Document>
I already tried to experiment with a <unique>
constraint, unfortunately without much success. Is there a way define such an exclusive enumeration per document?
Upvotes: 1
Views: 1447
Reputation: 111630
You cannot constrain all Country
elements to have the same one of several values simultaneously. Alternatives:
Country
elements in a document to be a
certain, preselected, value simultaneously via a fixed
attribute.Country
value out of each Address
and stored instead in a single,
common location in the document, such as an attribute or child element
of Items
or Document
.An xsd:assertion
could express your constraint:
<xs:assert test="count(distinct-values(en:Items/en:Address/en:Country)) = 1"/>
Here it is in the context of your complete XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:en="urn:enumtest"
targetNamespace="urn:enumtest"
elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:simpleType name="Country">
<xs:restriction base="xs:string">
<xs:enumeration value="CH"/>
<xs:enumeration value="AT"/>
<xs:enumeration value="DE"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Address">
<xs:sequence>
<xs:element name="Street" type="xs:string"/>
<xs:element name="No" type="xs:integer"/>
<xs:element name="Code" type="xs:integer"/>
<xs:element name="Country" type="en:Country"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Items">
<xs:sequence>
<xs:element name="Address" type="en:Address" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:element name="Items" type="en:Items"/>
</xs:sequence>
<xs:assert test="count(distinct-values(en:Items/en:Address/en:Country)) = 1"/>
</xs:complexType>
</xs:element>
</xs:schema>
Upvotes: 2
Reputation: 163360
It can obviously be done using assertions in XSD 1.1, but I don't think it can be done in XSD 1.0.
Upvotes: 0