要求`xsi:type`的值是特定命名空间中的类型,而不管前缀如何

时间:2015-02-07 17:34:14

标签: xml xpath xpath-2.0

说我有以下XML文件:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo="http://foo"
   xsi:type="foo:SomeSubtypeOfA">
    boo
</A>

我希望要求XML实例是从A派生的特定类型,例如输入{http://foo}SomeSubtypeOfA(实际上就是上面的例子)。所以我使用以下XPath:

/*[@xsi:type='foo:SomeSubtypeOfA']  

...并检查是否成功返回节点。但是上面的XPath是有问题的,因为它依赖于任意前缀,因此它在以下文件中失败:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo2="http://foo"
   xsi:type="foo2:SomeSubtypeOfA">
    boo
</A>

...它会在以下文件中产生错误匹配:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo="http://fooX"
   xsi:type="foo:SomeSubtypeOfA">
    boo
</A>

为了摆脱错误匹配,我可以将XPath编写为:

/*[namespace::foo[.='http://foo'] and @xsi:type='foo:SomeSubtypeOfA'] 

但是仍然无法解释绑定到http://foo命名空间的其他前缀的可能性。如何编写上面的XPath,以便检查xsi:type属性中给出的类型的名称空间而不是它的前缀?

1 个答案:

答案 0 :(得分:3)

在XPath 2.0中你可以做到

/*[namespace-uri-from-QName(resolve-QName(@xsi:type, .)) = 'http://foo' and local-name-from-QName(resolve-QName(@xsi:type, .)) = 'SomeSubtypeOfA']

在XPath 1.0中,您需要执行类似

的操作
//*[namespace::*[name()=substring-before(../@xsi:type, ':')] = 'http://foo/']

(但这可能不允许类型在默认命名空间中)