为何带命名空间的XML Schema无法检测唯一性约束违规?
XML Schema唯一性约束在命名空间下失效的问题解决
问题描述
调试XML Schema校验时遇到以下问题:
- 定义的
UniqueParameterNameConstraint唯一性规则,无法检测到XML中两个<Parameter>的<Name>同为CREAM_AMOUNT的违规情况 - 移除XML和XSD中对
MySchema命名空间的引用后,约束可正常生效并检测到违规
原XML数据
<RecipeElement xmlns="urn:MySchema"> <Parameter> <Name>CREAM_AMOUNT</Name> </Parameter> <Parameter> <Name>CREAM_AMOUNT</Name> </Parameter> <Parameter> <Name>FLAVOR_AMOUNT</Name> </Parameter> <Parameter> <Name>MILK_AMOUNT</Name> </Parameter> <Parameter> <Name>SUGAR_AMOUNT</Name> </Parameter> </RecipeElement>
原XSD Schema
<xs:schema targetNamespace="urn:MySchema" xmlns="urn:MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:complexType name="ParameterType"> <xs:sequence> <xs:element name="Name" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="RecipeElementType"> <xs:sequence> <xs:element name="Parameter" type="ParameterType" minOccurs="0" maxOccurs="unbounded"> </xs:element> </xs:sequence> </xs:complexType> <xs:element name="RecipeElement" type="RecipeElementType"> <xs:unique name="UniqueParameterNameConstraint"> <xs:selector xpath="Parameter"/> <xs:field xpath="Name"/> </xs:unique> </xs:element> </xs:schema>
原因分析
XSD中设置了elementFormDefault="qualified",这表示所有局部元素(包括<Parameter>和<Name>)都属于目标命名空间urn:MySchema。但原XSD里的<xs:selector>和<xs:field>使用的XPath未指定命名空间,直接写Parameter和Name会匹配不到任何命名空间内的元素,导致唯一性约束根本无法生效。
解决方案
在XSD中为目标命名空间声明一个前缀,并在XPath中使用该前缀指定命名空间下的元素。修改后的XSD如下:
<xs:schema targetNamespace="urn:MySchema" xmlns="urn:MySchema" xmlns:ms="urn:MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:complexType name="ParameterType"> <xs:sequence> <xs:element name="Name" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="RecipeElementType"> <xs:sequence> <xs:element name="Parameter" type="ParameterType" minOccurs="0" maxOccurs="unbounded"> </xs:element> </xs:sequence> </xs:complexType> <xs:element name="RecipeElement" type="RecipeElementType"> <xs:unique name="UniqueParameterNameConstraint"> <xs:selector xpath="ms:Parameter"/> <xs:field xpath="ms:Name"/> </xs:unique> </xs:element> </xs:schema>
关键修改点
- 添加命名空间前缀声明:
xmlns:ms="urn:MySchema"(前缀ms可自定义) - 修改
<xs:selector>的XPath:ms:Parameter,明确指定选择urn:MySchema命名空间下的<Parameter>元素 - 修改
<xs:field>的XPath:ms:Name,指定选择命名空间下的<Name>元素
修改后,唯一性约束就能正确识别命名空间内的元素,检测到重复的Name值。
内容的提问来源于stack exchange,提问作者Calethon
相关产品推荐
相关产品推荐

