用下面的 XML 片段更容易说明我的问题:
<Hosts>
<Host Ip1="1.2.3.4" Ip2="1.2.3.5" />
<Host Ip1="1.2.3.6" Ip2="1.2.3.4" />
...
<Hosts>
有没有办法使用 XSD 验证 Ip1 和 Ip2 属性的所有实例的值是唯一的?例如,上面的第二个元素将无法通过验证,因为它的 Ip2 值是第一个元素的 Ip1 值的副本。
谢谢!派鸿
用下面的 XML 片段更容易说明我的问题:
<Hosts>
<Host Ip1="1.2.3.4" Ip2="1.2.3.5" />
<Host Ip1="1.2.3.6" Ip2="1.2.3.4" />
...
<Hosts>
有没有办法使用 XSD 验证 Ip1 和 Ip2 属性的所有实例的值是唯一的?例如,上面的第二个元素将无法通过验证,因为它的 Ip2 值是第一个元素的 Ip1 值的副本。
谢谢!派鸿
该xsd:unique
约束旨在提供这种功能,但它受到特定方式的约束,因此很难看出如何表达您心中的特定约束。(也就是说,可能可以表达您心中的约束,但我自己看不到方法。)
为了其他阅读本文的人的利益,可能值得详细说明这个问题。约束的明显表述是这样的:
<!--* Not conformant *-->
<xs:unique name="hostip">
<xs:selector xpath="Host/@Ip1 | Host/@Ip2"/>
<xs:field xpath="."/>
</xs:unique>
但是,这不是一个一致的唯一性约束,因为管理选择器的临时约束不允许属性轴。(定义这些约束是为了确保验证器不必将整个文档保存在内存中并涵盖人们认为他们需要的情况。显然没有人认为他们需要检查属性节点值的唯一性,因此定义了 XPath 的子集for selectors 只能选择元素节点。考虑到 XSD 1.0 的设计者试图将元素和属性放在相似的基础上的长度,这看起来是一个显着的设计错误。)
一些读者可能会想到另一种表述,即:
<xs:selector xpath="Host"/>
<xs:field xpath="@Ip1|@Ip2"/>
这也是不一致的,因为对于任何选择器,每个字段表达式必须最多返回一个值。
如果您可以重新格式化 XML 以采用以下形式
<Hosts>
<Host>
<Ip>1.2.3.4</Ip>
<Ip>1.2.3.5</Ip>
<Host>
<Host>
<Ip>1.2.3.6</Ip>
<Ip>1.2.3.4</Ip>
<Host>
...
</Hosts>
xs:unique
然后您可以通过将以下元素添加到元素声明中来强制执行您想到的唯一性约束Hosts
:
<xs:unique name="hostip">
<xs:selector xpath="Host/Ip"/>
<xs:field xpath="."/>
</xs:unique>
它具有将 1.2.3.4 的重复标记为 IP 值的预期效果。