作为 Java 6 应用程序的一部分,我想在 XML 文档中查找所有名称空间声明,包括任何重复项。
编辑:根据 Martin 的要求,这是我正在使用的 Java 代码:
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression xPathExpression = xPathExpression = xPath.compile("//namespace::*");
NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDomDocument, XPathConstants.NODESET);
假设我有这个 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>
为了查找所有命名空间声明,我使用 xPath 1.0将此 xPath 语句应用于 XML 文档:
//namespace::*
它找到了 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
但是,如果我改为使用 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
即使我使用 xPath 语句的非缩写版本,也会看到同样的差异:
/descendant-or-self::node()/namespace::*
在 oXygen 中测试的各种 XML 解析器(LIBXML、MSXML.NET、Saxon)中都可以看到它。(编辑:正如我稍后在评论中提到的,这种说法是不正确的。虽然我认为我正在测试各种 XML 解析器,但我真的不是。)
问题一: 为什么从 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>
期望的结果是:
/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