我正在努力解决在xml架构中正确使用xsd:key元素的问题,以保留记录的唯一性。 我已经看到了许多有效的例子,但当我尝试利用它们来满足我的需求时,我无法达到预期的效果。
这是一个由我编写的简单示例,它没有按预期工作:
KeyTest.xml
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<KeyTest xmlns="keytest"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="keytest keytest.xsd">
<ManyThings>
<OneThing>
<Id>a</Id>
</OneThing>
<OneThing>
<Id>b</Id>
</OneThing>
<OneThing>
<Id>b</Id>
</OneThing>
</ManyThings>
</KeyTest>
KeyTest.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="keytest"
xmlns="keytest"
elementFormDefault="qualified">
<xs:element name="KeyTest">
<xs:complexType>
<xs:all>
<xs:element name="ManyThings" type="ManyThingsType">
<xs:key name="PK_ManyThings">
<xs:selector xpath="OneThing"/>
<xs:field xpath="Id"/>
</xs:key>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="ManyThingsType">
<xs:sequence maxOccurs="unbounded">
<xs:element name="OneThing" type="OneThingType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="OneThingType">
<xs:all>
<xs:element name="Id" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:schema>
我希望验证者拒绝KeyTest.xml,因为有多个记录带有Id&#34; b&#34;。但是,KeyTest.xml被认为是有效的。你能指出我代码中的错误吗?
我一直在使用Utilties Online Validator来验证我的文件。 我是xml / xsd初学者,所以请考虑一下我可能犯了一些基本错误的事实。
答案 0 :(得分:1)
您的问题似乎是XSD键中的XPath表达式默认为XPath 1.0规则,该规则表示未加固定的QNames,如&#34; Id
&#34;在您的字段规范中匹配不合格的元素。
您的键约束是在扩展名为Q {keytest} ManyThings的元素上定义的,并且它选择了名为Q {} OneThing的元素的子元素,并要求这些子元素需要一个名为Q的子元素{}具有唯一值的ID。这样就可以了,除了你的模式的其余部分指定Q {keytest} ManyThings的子项和子项分别是命名空间限定的元素,Q {keytest} OneThing和Q {keytest} Id。
在XSD 1.1中修复此问题的一种方法是在架构元素(或选择器和字段元素)上使用xpathDefaultNamespace
属性,并为其提供值&#34; keytest&#34;。我不知道您使用的验证服务是否支持XSD 1.1。
另一种在1.1或1.0中工作的方法是将显式名称空间前缀绑定到目标名称空间,例如:通过在架构文档上编写xmlns:keytest="keytest"
,然后在XPath表达式中使用该前缀:
<xs:key name="PK_ManyThings">
<xs:selector xpath="keytest:OneThing"/>
<xs:field xpath="keytest:Id"/>
</xs:key>
当我执行后者时,Saxon和Xerces J都会在XML中找到错误。