XML 序列 order/restriction 的架构基于属性值
XML Schema for sequence order/restriction based on attribute value
是否可以在 XML Schema 中定义一个基于属性值的序列 order/restriction?
在XML中,有container
个节点只保留了item
个节点。第一个 item
节点总是 delimiter
,其他 item
节点必须只有属性值 category1
OR category2
.
例如,有效文件为:
<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>
在 container
节点中,我们只能有 item
个节点 category1
或 category2
.
不正确的例子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>
XSD可以吗?
直接回答你的问题,是的,这在 XSD 中是可能的,但是:
- 它需要 XSD 1.1(见下面的 XSD 1.1 原始 XML);在 XSD 1.0:
中无法完成
这是糟糕的XML设计。更好的做法如下,可以很容易地用 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>
XSD 1.1 请求,原始 XML
<?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>
是否可以在 XML Schema 中定义一个基于属性值的序列 order/restriction?
在XML中,有container
个节点只保留了item
个节点。第一个 item
节点总是 delimiter
,其他 item
节点必须只有属性值 category1
OR category2
.
例如,有效文件为:
<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>
在 container
节点中,我们只能有 item
个节点 category1
或 category2
.
不正确的例子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>
XSD可以吗?
直接回答你的问题,是的,这在 XSD 中是可能的,但是:
- 它需要 XSD 1.1(见下面的 XSD 1.1 原始 XML);在 XSD 1.0: 中无法完成
这是糟糕的XML设计。更好的做法如下,可以很容易地用 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>
XSD 1.1 请求,原始 XML
<?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>