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

时间:2012-10-11 18:04:25

标签: xsd xsd-validation

使用下面的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值的副本。

谢谢! PAI-红

1 个答案:

答案 0 :(得分:0)

xsd:unique约束旨在提供此类功能,但它以临时方式受到限制,这使得很难看到如何表达您想到的特定约束。 (也就是说,有可能表达你想到的约束,但我看不出办法,我自己。)

为了阅读本文的其他人的利益,详细说明问题可能是值得的。约束的明显表述是:

<!--* Not conformant *-->
<xs:unique name="hostip">
  <xs:selector xpath="Host/@Ip1 | Host/@Ip2"/>
  <xs:field xpath="."/>
</xs:unique>
但是,这不是一致的唯一性约束,因为管理选择器的ad hoc约束不允许属性轴。 (这些约束被定义为确保验证器不必将整个文档保存在内存中并覆盖人们认为需要的情况。显然没有人认为他们需要检查属性节点值的唯一性,因此XPath的子集已定义对于选择器只能选择元素节点。考虑到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值的预期效果。