Document声明单独的空命名空间呈现NamespaceAware结果无用

Vog*_*612 6 java xpath jdom jdom-2

我正在尝试对maven使用的"正确"pom.xml执行一些检索查询.为此我使用JDOM的基本XPath查询.

不幸的是,查询不返回任何结果(简单的后代过滤器也没有).我有理由相信问题在于pom.xml的根声明:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<!-- content -->
</project>
Run Code Online (Sandbox Code Playgroud)

可以看出一个空的命名空间定义不匹配或者""还是"http://www.w3.org/2000/xmlns/",其中""是默认的无命名空间和命名空间的xmlns是默认的xmlns命名空间.

所以给定一个Document,当我想执行XPath-Query时,如下所示:

XPathBuilder<Element> depQueryBuilder = new XPathBuilder<>("//dependencies/dependency", Filters.element());
XPathExpression<Element> depQuery = depQueryBuilder.compileWith(XPathFactory.instance());

for  (Element elem : depQuery.evaluate(document)) {
    // basically unreachable, since the resultset is always empty
}
Run Code Online (Sandbox Code Playgroud)

鉴于所有XPath表达式和查询都需要知道名称空间(比较XPathHelper javadoc),我很确定我可以通过添加必需的名称空间声明来实现这一点.

我尝试了以下不同类型的失败:

depQueryBuilder.setNamespace("", document.getRootElement().getAttributeValue("xmlns"));
// NPE: Null URI
depQueryBuilder.setNamespace("", "http://maven.apache.org/POM/4.0.0");
// Cannot set a Namespace URI in XPath for "" prefix
depQueryBuilder.setNamespace(Namespace.NO_NAMESPACE);
// no error-message, but no results either
depQueryBuilder.setNamespace(document.getRootElement().getNamespace("xmlns"));
// NPE: Null Namespace
depQueryBuilder.setNamespace(document.getRootElement().getNamespace(""));
// Cannot set a Namespace URI in XPath for "" prefix
depQueryBuilder.setNamespace("xmlns", "http://maven.apache.org/POM/4.0.0");
// Name "xmlns" is not legal for JDOM/XML Namespace prefix
Run Code Online (Sandbox Code Playgroud)

在这一点上,我甚至不确定我是否正确地攻击了这一点.如何让我的XPath查询返回结果?

注意:以下更简单的查询也不会返回结果:

document.getRootElement().getDescendants(Filter.element("dependency"));
// empty iterator
document.getRootElement().getChild("dependencies").getChildren("dependency"));
// NullPointerException because there is no child "dependencies"
Run Code Online (Sandbox Code Playgroud)

rol*_*lfl 4

XPath 查询和 XML 中的一般文档导航需要有效使用命名空间。

特别是 XPath 不遵循与常规 XML 文档相同的规则,因为命名空间的处理存在差异""。在 XML 文档中,它指的是“默认”命名空间(无命名空间或通过使用 声明来覆盖该命名空间的任何内容xmlns="....")。

然而,在 XPath 中,规则略有不同(请参阅规范-重点是我的):

使用表达式上下文中的命名空间声明将节点测试中的 QName 扩展为扩展名称。这与开始和结束标签中元素类型名称的扩展方式相同,只是不使用使用 xmlns 声明的默认命名空间:如果 QName 没有前缀,则命名空间 URI 为 null

这实际上意味着,即使您不需要 XML 中的命名空间前缀(例如 )dependencies,您仍然需要 XPath 查询中的前缀。前缀可以是任何内容 - 不需要与 XML 文档中的任何内容匹配。因此,选择像“ns”这样的任意名称空间,您可以进行查询:

XPathBuilder<Element> depQueryBuilder = new XPathBuilder<>("//ns:dependencies/ns:dependency", Filters.element());
depQueryBuilder.setnamespace("ns", "http://maven.apache.org/POM/4.0.0");
XPathExpression<Element> depQuery = depQueryBuilder.compileWith(XPathFactory.instance());
Run Code Online (Sandbox Code Playgroud)

这可以通过以下方式更简单地完成:

Namespace ns = Namespace.getNamespace("ns", "http://maven.apache.org/POM/4.0.0");
XPathExpression<Element> depQuery = XPathFactory.instance()
  .compile("//ns:dependencies/ns:dependency", Filters.element(), null, ns);
Run Code Online (Sandbox Code Playgroud)