'XSD restrict content of element depending on attributes value
Formally our XSD looked like this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="fooxsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="List">
<xs:complexType>
<xs:sequence>
<xs:element name="Config" type="ConfigType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Entry">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="key" type="xs:ID" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
XMLs can look like this:
<?xml version="1.0" encoding="utf-8"?>
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
<Entry key="foo">bar</Config>
<Entry key="baz">boom</Config>
</List>
- all entries are optional
- all keys have to be unique
- order of keys are irrelevant
Nothing but a key-value list.
Now I have a list of constraints like this:
- foo can only be "bar2 or "bar2"
- baz can only be "boom" or "box"
I want to put this list into the XSD, so XML-authors can not enter undefined keys or values which are not allowed for that key.
I know it would be better to get rid of the key-attribute, and make something like
<List>
<foo>bar</foo>
<baz>boom</foo>
</List>
But unfortunately I can not; the format must remain the same. But with more restrictions. I have to restrict the content depending to what's given in the key-attribute.
I read
Here the <xs:assert>-element is mentioned in the second answer - that could be a solution. An ugly one though, but maybe there is better one using the usual xsd-elements?
Solution 1:[1]
In XML Schema 1.1, xs:alternative can specify attribute-dependent types, as shown at your link (Restrict XSD attribute value based on another attribute value).
For your example, a schema might look like the following:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsv="http://www.w3.org/2007/XMLSchema-versioning"
elementFormDefault="qualified"
xsv:minVersion="1.1">
<xs:element name="List">
<xs:complexType>
<xs:sequence>
<xs:element name="Config" minOccurs="0" maxOccurs="unbounded">
<xs:alternative test="@key='foo'" type="ConfigKeyFooType"/>
<xs:alternative test="@key='baz'" type="ConfigKeyBazType"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="ConfigTypeAttributeGroup">
<xs:attribute name="key" type="xs:ID" use="required" />
</xs:attributeGroup>
<xs:complexType name="ConfigKeyFooType">
<xs:simpleContent>
<xs:extension base="ConfigKeyFooContentType">
<xs:attributeGroup ref="ConfigTypeAttributeGroup"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="ConfigKeyFooContentType">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="bar"/>
<xs:enumeration value="bar2"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ConfigKeyBazType">
<xs:simpleContent>
<xs:extension base="ConfigKeyBazContentType">
<xs:attributeGroup ref="ConfigTypeAttributeGroup"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="ConfigKeyBazContentType">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="boom"/>
<xs:enumeration value="box"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
A valid xml…
<?xml version="1.0" encoding="utf-8"?>
<List>
<Config key="foo">bar</Config>
<Config key="baz">boom</Config>
</List>
…is assessed as valid.
An invalid xml due to duplicate keys…
<?xml version="1.0" encoding="utf-8"?>
<List>
<Config key="foo">bar</Config>
<Config key="baz">boom</Config>
<Config key="foo">bar2</Config>
<Config key="baz">box</Config>
</List>
…is assessed as invalid with messages:
[Error] sample-bad-dup-keys.xml:5:21:cvc-id.2: There are multiple occurrences of ID value 'foo'.
[Error] sample-bad-dup-keys.xml:5:21:cvc-attribute.3: The value 'foo' of attribute 'key' on element 'Config' is not valid with respect to its type, 'ID'.
[Error] sample-bad-dup-keys.xml:6:21:cvc-id.2: There are multiple occurrences of ID value 'baz'.
[Error] sample-bad-dup-keys.xml:6:21:cvc-attribute.3: The value 'baz' of attribute 'key' on element 'Config' is not valid with respect to its type, 'ID'.
An invalid xml due to invalid values…
<?xml version="1.0" encoding="utf-8"?>
<List>
<Config key="foo">bar3</Config>
<Config key="baz">boox</Config>
</List>
…is assessed as invalid with messages:
[Error] sample-bad-values.xml:3:34:cvc-enumeration-valid: Value 'bar3' is not facet-valid with respect to enumeration '[bar, bar2]'. It must be a value from the enumeration.
[Error] sample-bad-values.xml:3:34:cvc-complex-type.2.2: Element 'Config' must have no element [children], and the value must be valid.
[Error] sample-bad-values.xml:4:34:cvc-enumeration-valid: Value 'boox' is not facet-valid with respect to enumeration '[boom, box]'. It must be a value from the enumeration.
[Error] sample-bad-values.xml:4:34:cvc-complex-type.2.2: Element 'Config' must have no element [children], and the value must be valid.
Tested with Online Schema Validator service (linked from Xerces Using XML Schemas) running "Apache Xerces-J (v 2.12.2) XML Schema validator".
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | user9712582 |