Java XPath处理器忽略NamespaceContext 无法查询默认命名空间节点
问题原因
- 你使用的JDK默认XPath 1.0处理器不支持XPath表达式中无前缀节点匹配默认命名空间的规则:XPath 1.0规范明确规定,表达式中不带前缀的节点名,只会匹配没有命名空间的节点,不会触发你给
XMLConstants.DEFAULT_NS_PREFIX绑定的命名空间逻辑。 - 你编写的XPath表达式
/project/name/text()里所有节点都没有前缀,处理器不需要查询任何前缀对应的命名空间URI,所以根本不会调用你实现的NamespaceContext的方法,自然没有***开头的日志输出,也匹配不到带默认命名空间的project、name节点。
解决方法
- 给XPath表达式里的节点添加自定义前缀,比如我们用
pom作为前缀,修改表达式为/pom:project/pom:name/text() - 调整NamespaceContext的
getNamespaceURI实现,把自定义前缀pom和目标命名空间http://maven.apache.org/POM/4.0.0绑定
修改后的关键代码片段如下:
// 修改后的XPath表达式编译代码 XPathExpression xpathExpressionNS = xpathNS.compile("/pom:project/pom:name/text()"); // 修改后的NamespaceContext的getNamespaceURI方法 @Override public String getNamespaceURI(String prefix) { System.out.println("*** getNamespaceURI, prefix='" + prefix + "'"); // 匹配自定义前缀pom if ("pom".equals(prefix)) { System.out.println("*** returning maven POM namespace URL"); return "http://maven.apache.org/POM/4.0.0"; } System.out.println("*** returning NULL_NS_URI"); return XMLConstants.NULL_NS_URI; }
修改后运行即可看到预期的***日志,同时artifactIdNS会正确返回test-repo-1的值。如果你切换到Saxon等支持XPath 2.0+的处理器,也可以通过配置默认命名空间匹配规则实现无前缀节点匹配默认命名空间的需求。
内容的提问来源于stack exchange,提问作者Michael Resnick
相关产品推荐
相关产品推荐

