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 个节点 category1category2.

不正确的例子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 中是可能的,但是:

  1. 它需要 XSD 1.1(见下面的 XSD 1.1 原始 XML);在 XSD 1.0:
  2. 中无法完成
  3. 这是糟糕的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>