我正在尝试使用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>
请建议我是否遵循正确的方法,如果我遵循正确的方法,任何人都可以向我提供如何实现这一限制的代码吗?在此先感谢...
答案 0 :(得分:10)
你越来越近了。
在XSD 1.1中,断言只能向下查看子树,而不是向上或向上,所以如果你想在这里使用断言,你会想要把它们放在'state'的类型中但是在''的类型中地址:
<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表达式为元素分配不同的类型,XPath表达式可以引用其元素(但不能引用其子元素)。如果我们将country和state移动到属性(然后,为了保持一致性,将street和city移动到属性),我们可以使用条件类型赋值。首先,定义我们想要的各种简单类型:
<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>
现在我们根据'country'的值将address
元素绑定到其中一个元素:
<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的方法指定类型。最后一个替代方法(没有测试属性)提供了一个默认值,在这种情况下是错误类型(没有元素或属性对错误类型有效)。