XSD基于多个元素的唯一约束,包括可选元素

时间:2013-12-11 11:05:15

标签: xml validation xsd

我在多个元素上定义了一个唯一约束:define unique constraint based on multiple elements

现在唯一约束看起来像这样:

<xs:unique name="specieSizeGroupLengthAssortment">
    <xs:selector xpath="DataRow"/>
    <xs:field xpath="Specie"/>
    <xs:field xpath="Group"/>
    <xs:field xpath="Length"/>
    <xs:field xpath="Type"/>
</xs:unique>   

现在假设元素“Type”是可选的。到目前为止,我的搜索和我的测试证实,这个唯一约束仅适用于具有唯一约束中定义的所有子元素的元素。 例如:

由于唯一约束,这应该是无效

<DataRow>
   <Specie>A</Specie>
   <Length>100</Length>
   <Group>A</Group>
</DataRow>

<DataRow>
   <Specie>A</Spacie>
   <Length>100</Length>
   <Group>A</Group>
</DataRow>

这应该有效

<DataRow>
   <Specie>A</Specie>
   <Length>100</Length>
   <Group>A</Group>
</DataRow>

<DataRow>
   <Specie>A</Spacie>
   <Length>100</Length>
   <Group>A</Group>
   <Type>D</Type>
</DataRow>

这应该是无效

<DataRow>
   <Specie>A</Specie>
   <Length>100</Length>
   <Group>A</Group>
   <Type>D</Type>
</DataRow>

<DataRow>
   <Specie>A</Spacie>
   <Length>100</Length>
   <Group>A</Group>
   <Type>D</Type>
</DataRow>

是否可以创建一个可以进行此类验证的XSD架构?

2 个答案:

答案 0 :(得分:3)

规范声明field约束中的每个unique

  

必须标识单个节点(元素或属性),其内容或值必须是简单类型,才能在约束中使用。

XML Schema part 1: Structures, §3.11.1,我的大胆。

因此,您似乎无法在唯一性约束中使用可选元素。这由用于验证这些约束的逐步规则(§3.11.4)支持:

  

3对于目标节点集中的每个节点,所有{fields}(以该节点作为上下文节点)将评估为空节点集或具有恰好一个成员的节点集,其必须具有一个简单的类型。 [定义:]调用元素的[模式规范化值]中定义的类型确定值的序列(如[XML Schemas:Datatypes]中所定义)和/或那些节点集中的属性信息项,以便节点的键序列   4 [定义:]调用·目标节点集的子集·所有{fields}求值为具有一个成员的节点集,该成员是具有限定节点集的简单类型的元素或属性节点即可。以下适当的情况必须如此:
  4.1如果{identity-constraint category}是唯一的,那么合格节点集的两个成员没有·key-sequences·其成员成对相等,如[XML Schemas:Datatypes]中的Equal所定义。
  [...]

这明确地将唯一性检查定义为仅应用于“限定节点集”,即与selector匹配的节点 all field s < / p>

答案 1 :(得分:1)

我想我的方法错了。唯一约束允许缺少字段;关键限制没有。

该语言非常模糊,但在XSD 1.1版本中更易于理解,因为已添加了一些注释。我不认为两个版本之间的功能有任何(故意)改变。

  • {selector}以元素信息项作为上下文节点,求值为一个节点集(如[XPath]中所定义)。 [定义:]将此称为目标节点集。

  • 将所有{fields}求值的目标节点集的子集调用为具有一个成员的节点集,该成员是具有限定节点集的简单类型的元素或属性节点。 / p>

因此,如果某个选定节点的某个字段缺少值,则此节点不属于限定节点集。

  • 如果{identity-constraint category}是唯一的,那么没有合格节点集的两个成员·[may]可能具有成员相等的键序列,如[XML Schemas:Datatypes]中的Equal所定义的那样]

这意味着对于“唯一”,将忽略不存在字段的所选节点。

  • 如果{identity-constraint category}是关键字,那么以下所有内容必须为true: 4.2.1·目标节点集·和·合格节点集·相等,即·目标节点集的每个成员·也是·合格节点集的成员·反之亦然。

这意味着对于“key”,如果缺少其中一个字段,则数据无效。

我还得出结论,发布的原始模式几乎完成了所需的操作,但第一个示例不是无效的:对于两个选定的节点都有一个字段缺失,因此在选定的节点中都没有包含选定的节点 - 因此,唯一约束无效。要使其无效,您将需要第二个“唯一”约束,该约束仅列出前三个字段。但是,如果这三个字段相同,即使第四个字段存在,您也会得到有效性错误。

在XSD 1.1中,您可以使用断言

来解决问题
test="count(DataRow) = count(distinct-values(DataRow/concat(
                         Specie, '|', Length, '|', Group, '|', Type)))