如何使用XPath获取嵌套默认命名空间的XML元素
解决XPath无法匹配带默认命名空间的节点问题
你的问题核心就是xmlns属性时,该元素及其子元素都会属于这个默认命名空间。而你开启了命名空间感知(dbf.setNamespaceAware(true)),此时XPath中直接写root会被解析为无命名空间的元素,自然匹配不到实际属于http://www.example.com命名空间的
解决步骤:
- 扩展NamespaceContext,为默认命名空间绑定前缀
给http://www.example.com这个默认命名空间绑定一个自定义前缀(比如def,前缀名称可随意,只要和URI对应即可),同时完善NamespaceContext的所有方法(避免部分XPath引擎出现异常):
xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { switch (prefix) { case "abc": return "http://www.example.com/abc"; case "def": return "http://www.example.com"; // 映射默认命名空间 default: return null; } } @Override public String getPrefix(String namespaceURI) { if (namespaceURI.equals("http://www.example.com/abc")) { return "abc"; } else if (namespaceURI.equals("http://www.example.com")) { return "def"; } return null; } @Override public Iterator<String> getPrefixes(String namespaceURI) { List<String> prefixes = new ArrayList<>(); if (namespaceURI.equals("http://www.example.com/abc")) { prefixes.add("abc"); } else if (namespaceURI.equals("http://www.example.com")) { prefixes.add("def"); } return prefixes.iterator(); } });
- 修改XPath表达式,使用绑定的前缀匹配
将原来的//abc:test-object/root修改为//abc:test-object/def:root,明确指定属于 def前缀对应的命名空间:
XPathExpression expr = xpath.compile("//abc:test-object/def:root"); Node node = (Node) expr.evaluate(doc, XPathConstants.NODE);
原理说明
在命名空间感知的XML处理逻辑中,元素的唯一标识是命名空间URI + 本地名称,前缀只是URI的别名。通过给默认命名空间绑定前缀,XPath就能正确识别
内容的提问来源于stack exchange,提问作者dominikm
相关产品推荐
相关产品推荐

