且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 XSD 1.1 的动态枚举限制

更新时间:2022-06-09 18:18:03

你已经接近了.

在 XSD 1.1 中,断言只能向下查看子树,不能向上或向上,所以如果你想在这里使用断言,你需要把它们放在 'state' 类型而不是 '地址:

In XSD 1.1, assertions can only look down into the subtree, not up or over, so if you want to use assertions here, you will want to put them not in the type for 'state' but in the type for 'address':

<xs:element name="address">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="street"/>
      <xs:element ref="city"/>
      <xs:element ref="state" minOccurs="0"/>
      <xs:element ref="country"/>
    </xs:sequence>
    <xs:assert test="(country = 'UK' and not(state))
      or
      (country = 'US' and state = ('MA', 'AR', 'NY'))
      or
      (country = 'IN' and state = ('AP', 'TN', 'MP'))
      "/>
  </xs:complexType>
</xs:element>

另一种方法(也在 XSD 1.1 中)是使用条件类型赋值.这允许基于可以引用其元素(但不能引用其子元素)的 XPath 表达式为元素分配不同的类型.如果我们将国家和州移动到属性中(然后,为了保持一致性,也将街道和城市移动到属性中),我们可以这样使用条件类型分配.首先,为状态定义我们想要的各种简单类型:

A different approach (also in XSD 1.1) is to use conditional type assignment. This allows an element to be assigned different types based on XPath expressions which can refer to its elements (but not its children). If we move country and state to attributes (and then, for consistency, move street and city to attributes as well), we could use conditional type assignment this way. First, define the various simple types we want for state:

<xs:simpleType name="US-states">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="MA" />
    <xs:enumeration value="AR" />
    <xs:enumeration value="NY" />      
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="IN-states">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="AP" />
    <xs:enumeration value="TN" />
    <xs:enumeration value="MP" />   
  </xs:restriction>
</xs:simpleType>

然后为我们想要的三种不同类型的地址定义三种不同的复杂类型.我假设英国地址没有州"属性.

Then define three different complex types for the three different kinds of addresses we want. I'm assuming for illustration that UK addresses don't get a 'state' attribute.

<xs:complexType name="US-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="state" type="US-states"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="UK-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="IN-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="state" type="IN-states"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>

现在我们根据 'country' 的值将 address 元素绑定到正确的其中之一:

Now we bind the address element to the correct one of these based on the value of 'country':

<xs:element name="address">
  <xs:alternative test="@country='US'" type="US-address"/>
  <xs:alternative test="@country='IN'" type="IN-address"/>
  <xs:alternative test="@country='UK'" type="UK-address"/>
  <xs:alternative type="xs:error"/>
</xs:element>

备选方案按顺序进行测试,第一个测试结果为 true 的备选方案分配类型.最后一种选择(没有测试属性)提供了一个默认值,在这种情况下是错误类型(没有元素或属性对错误类型有效).

The alternatives are tested in order, and the first one whose test evaluates to true assigns the type. The last alternative (without a test attribute) provides a default, which in this case is the error type (no elements or attributes are valid against the error type).