查找XML文档中的所有名称空间声明 - xPath 1.0 vs xPath 2.0

jam*_*iss 6 java xml xpath saxon xml-namespaces

作为Java 6应用程序的一部分,我想在XML文档中查找所有名称空间声明,包括任何重复项.

编辑:Per Martin的请求,这是我正在使用的Java代码:

XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression xPathExpression = xPathExpression = xPath.compile("//namespace::*"); 
NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDomDocument, XPathConstants.NODESET);
Run Code Online (Sandbox Code Playgroud)

假设我有这个XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:ele="element.com" xmlns:att="attribute.com" xmlns:txt="textnode.com">
    <ele:one>a</ele:one>
    <two att:c="d">e</two>
    <three>txt:f</three>
</root>
Run Code Online (Sandbox Code Playgroud)

要查找所有名称空间声明,我使用xPath 1.0将此xPath语句应用于XML文档:

//namespace::*
Run Code Online (Sandbox Code Playgroud)

它找到4个名称空间声明,这是我期望(和期望):

/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改为使用XPath 2.0,然后我得到16点命名空间声明(每个先前声明的4倍),这不是我所期望(或希望):

/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
Run Code Online (Sandbox Code Playgroud)

即使我使用xPath语句的非缩写版本,也会看到同样的差异:

/descendant-or-self::node()/namespace::*
Run Code Online (Sandbox Code Playgroud)

在oXygen中测试的各种XML解析器(LIBXML,MSXML.NET,Saxon)中都可以看到它.(编辑:正如我在后面的评论中提到的,这种说法不正确.虽然我认为我正在测试各种XML解析器,但我真的不是.)

问题1: 为什么从xPath 1.0到xPath 2.0的区别?

问题2: 使用xPath 2.0获得所需结果是否可能/合理?

提示:使用distinct-values()xPath 2.0中的函数将不会返回所需的结果,因为我想要所有名称空间声明,即使同一名称空间被声明两次.例如,考虑这个XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <bar:one xmlns:bar="http://www.bar.com">alpha</bar:one>
    <bar:two xmlns:bar="http://www.bar.com">bravo</bar:two>
</root>
Run Code Online (Sandbox Code Playgroud)

期望的结果是:

/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/bar:one[1]/@xmlns:bar - http://www.bar.com
/root[1]/bar:two[1]/@xmlns:bar - http://www.bar.com
Run Code Online (Sandbox Code Playgroud)

Rog*_*llo 7

我认为这将获得所有名称空间,没有任何重复:

for $i in 1 to count(//namespace::*) return 
if (empty(index-of((//namespace::*)[position() = (1 to ($i - 1))][name() = name((//namespace::*)[$i])], (//namespace::*)[$i]))) 
then (//namespace::*)[$i] 
else ()
Run Code Online (Sandbox Code Playgroud)