<xsd:key>元素 - 如何正确使用它?</xsd:key>

时间:2014-10-01 14:51:17

标签: xml xsd key primary-key xsd-validation

我正在努力解决在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初学者,所以请考虑一下我可能犯了一些基本错误的事实。

1 个答案:

答案 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中找到错误。