7

我正在尝试使用 XSD 1.1 创建一个模式定义,其中一个元素的结果依赖于另一个元素。例如,我有国家列表和每个国家的州列表的下拉列表。当一个人选择一个国家时,只能选择那个国家的州。我试图达到的伪代码看起来像这样。

<xs:schema xmlns:ie="http://www.interviewexchange.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="country">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="USA" />
            <xs:enumeration value="UK" />
            <xs:enumeration value="India" />
        </xs:restriction>
    </xs:simpleType>
</xs:element>
<xs:element name="state">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <assert test="if (country eq 'USA')">
            <xs:enumeration value="MA" />
            <xs:enumeration value="AR" />
            <xs:enumeration value="NY" />
            </assert">
            <assert test="if (country eq 'India')">
            <xs:enumeration value="AP" />
            <xs:enumeration value="TN" />
            <xs:enumeration value="MP" />
            </assert">
        </xs:restriction>
    </xs:simpleType>
</xs:element>

请建议我是否遵循正确的方法,如果我遵循正确的方法,谁能给我如何达到此限制的代码?提前致谢...

4

1 回答 1

10

你越来越近了。

在 XSD 1.1 中,断言只能向下查看子树,不能向上或向上,所以如果你想在这里使用断言,你需要把它们放在 'state' 类型而不是 '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 表达式为元素分配不同的类型。如果我们将国家和州移动到属性中(然后,为了保持一致性,也将街道和城市移动到属性中),我们可以这样使用条件类型分配。首先,为状态定义我们想要的各种简单类型:

<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>

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

<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>

现在我们address根据 '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 的备选方案分配类型。最后一种选择(没有测试属性)提供了一个默认值,在这种情况下是错误类型(没有元素或属性对错误类型有效)。

于 2012-12-12T17:59:25.710 回答