Reputation: 1
I am new to XML schema and I am trying to figure out how to set up restrictions based on another value.
For example:
"State" = RI --> valid value is ABS only for this state "State" = NC or CT valid value is Y only for either state
The following xml schema is allowing ABS and Y regardless of the state:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="State">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="RI"/>
<xs:enumeration value="CT"/>
<xs:enumeration value="NC"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="PersonalInfo">
<xs:complexType>
<xs:sequence>
<xs:element ref="State"/>
<xs:element ref="Car"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Manufacturer">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="MINI"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Car">
<xs:complexType>
<xs:sequence>
<xs:element ref="Manufacturer"/>
<xs:element ref="AntiLockBrakes"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="AntiLockBrakes">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="ABS"/>
<xs:enumeration value="Y"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
Upvotes: 0
Views: 1572
Reputation: 25044
Because this class of constraint governs not the value of the separate elements involved taken individually, but the co-occurrence of particular values, they are often called co-occurrence constraints (or more tersely co-constraints).
Context-free grammars (and schema languages which essentially provide specialized vocabularies for writing context-free grammars for XML documents -- like DTDs, Relax NG, and XSD content models) don't deal well with co-constraints in the general case (although there are often special cases they can handle easily).
Predicate-based constraint languages (like Schematron and like assertions in XSD 1.1) are often able to express co-constraints conveniently, because they are built around the idea of predicates -- things that hold true, or do not hold true, of a document or an element or an attribute -- and typically allow predicates to be combined using Boolean operators.
So your best bet for enforcing the constraint you describe is to use Schematron, or assertions in XSD 1.1. In XSD 1.1 (unlike Schematron), assertions are not allowed to look outside the element to whose type the assertions are attached, so you need to put your assertion on the smallest element that contains both the State and the AntiLockBrakes element; if I'm reading the schema correctly, that will be PersonalInfo. An XSD 1.1 schema could use assertions to enforce your constraint by changing the declaration of PersonalInfo to read something like this:
<xs:element name="PersonalInfo">
<xs:complexType>
<xs:sequence>
<xs:element ref="State"/>
<xs:element ref="Car"/>
</xs:sequence>
<xs:assert test="
(State = 'RI' and Car/AntiLockBrakes = 'Y')
or
(State = ('NC', 'CT') and Car/AntiLockBrakes = 'ABS')
"/>
</xs:complexType>
</xs:element>
The assertion in the xs:assert element's 'test' attribute is expressed using XPath 2.0; as you might expect, there are a variety of ways one could express it.
Schematron works similarly, but Schematron does not in itself specify the language in which to express tests; it is easy to find Schematron implementations that support assertions written in XPath 1.0, or which accept XPath 2.0.
Upvotes: 3