如何限制扩展类型的属性

时间:2013-06-21 10:29:59

标签: xml xsd

我想从基类型派生元素。这个基类型(我们称之为实体)具有id属性。对于派生元素,我想对此属性添加限制(对不同的派生实体元素有不同的限制):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="Entity">
        <xs:attribute name="id">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="[A-Z]+[0-9]+"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
    <xs:element name="someEntity">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="Entity">
                    <xs:sequence>
                        <xs:element name="someAdditionalElement"/>
                    </xs:sequence>
                    <!-- I would like to restrict the attribute "id" for this entity to e.g. the pattern "SOME[0-9]+" -->
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="otherEntity">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="Entity">
                    <xs:sequence>
                        <xs:element name="otherAdditionalElement"/>
                    </xs:sequence>
                    <!-- I would like to restrict the attribute "id" for this entity to a differtnt pattern like e.g. "OTHER[0-9]+" -->
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
</xs:schema>

这是可能的,如果可以,怎么样?

1 个答案:

答案 0 :(得分:4)

当扩展类型时,您当然可以向类型Entity添加元素;在限制类型时,您当然可以限制id属性。您所描述的唯一不能做的是(1)同时扩展和限制类型,以及(2)'限制'一个id属性,它只接受大写字母字符串,允许它接受包含十进制的字符串数字也是。 (当MiMo说你无法做你想做的事情时,可能会想到这些。)

所以做你想做的事就是:

  1. 定义复杂类型Entity,其id属性允许您在派生类型上允许的所有id形式。
  2. 对于每个派生类型(在您的示例中,someEntity和otherEntity),首先派生实体的限制,然后派生该限制的扩展 - 反之亦然,首先是扩展,然后是限制。如果您不希望这些中间类型用于其他地方的任何元素,那么请将它们抽象化。
  3. 当您限制属性的类型(此处为id属性)时,XSD验证程序需要能够轻松查看新类型是旧类型的限制。因此,您不希望为Entity的id属性使用本地定义的类型;你想要一个定义的类型。因此,您需要使用两个声明替换您的Entity声明,如下所示:

    <xs:simpleType name="uppercase-alphanumeric-string">
      <xs:restriction base="xs:string">
        <xs:pattern value="[A-Z0-9]+"/>
      </xs:restriction>
    </xs:simpleType>
    
    <xs:complexType name="Entity">
      <xs:attribute name="id" type="uppercase-alphanumeric-string"/>
    </xs:complexType>
    

    然后,您可以通过两个步骤定义元素someEntity的类型。首先,定义一个具有适当的实体类型限制的复杂类型:

    <xs:complexType name="Entity-restriction-SOME" abstract="true">
      <xs:complexContent>
        <xs:restriction base="Entity">
          <xs:attribute name="id">
            <xs:simpleType>
              <xs:restriction base="uppercase-alphanumeric-string">
                <xs:pattern value="SOME[0-9]+"></xs:pattern>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:restriction>
      </xs:complexContent>
    </xs:complexType>
    

    如上所述,您可以执行限制然后扩展,或扩展然后限制。我首先要做的是限制,以避免必须为扩展类型重新指定内容模型。

    然后您可以通常的方式指定限制的扩展名:

    <xs:element name="someEntity">
      <xs:complexType>
        <xs:complexContent>
          <xs:extension base="Entity-restriction-SOME">
            <xs:sequence>
              <xs:element name="someAdditionalElement"/>
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:element>
    

    我会留下其他元素作为读者的练习。