验证XSD中多个属性值的唯一性



用下面的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子集只能选择元素节点和属性相似,这看起来是一个显著的设计错误。)

一些读者可能会想到另一种配方,即:

<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值的预期效果。

最新更新