Reputation: 13
Is it possible to define in XML Schema a sequence order/restriction based on attribute value?
In XML, there is container
node which keeps only item
nodes. First item
node is always delimiter
, other item
nodes must be only with attribute value category1
OR category2
.
For example, valid documents is:
<root>
<container>
<item attr="delimiter">some_value</item>
<item attr="category1">test1</item>
<item attr="category1">test2</item>
....
</container>
<container>
<item attr="delimiter">some_value</item>
<item attr="category2">test3</item>
...
</container>
<root>
In container
node we can have item
nodes only with category1
or category2
.
Example of incorrect XML:
<root>
<container>
<item attr="delimiter">some_value</item>
<item attr="category1">test1</item>
<item attr="category2">test2</item>
</container>
<container>
<item attr="delimiter">some_value</item>
<item attr="category2">test3</item>
<item attr="category1">test1</item>
</container>
<root>
Is it possible in XSD?
Upvotes: 1
Views: 1002
Reputation: 111630
To answer your question directly, yes, this is possible in XSD, however:
It is poor XML design. Better would be as follows, which could easily be represented in XSD 1.0:
<root>
<container>
<delimiter>some_value</delimiter>
<category1>test1</category1>
<category1>test2</category1>
....
</container>
<container>
<delimiter>some_value</delimiter>
<category2>test3</category2>
...
</container>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="container" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="delimiter"/>
<xs:enumeration value="category1"/>
<xs:enumeration value="category2"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:assert test="item[1]/@attr = 'delimiter' and
((every $i in item[position() > 1] satisfies $i/@attr = 'category1') or
(every $i in item[position() > 1] satisfies $i/@attr = 'category2')) "/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Upvotes: 3