Java中使用XPath处理命名空间时ns3前缀解析异常如何解决
问题根因
- 第一,DocumentBuilderFactory的命名空间感知配置顺序错误:你在
convertStringToXMLDocument方法里先创建了DocumentBuilder,才调用factory.setNamespaceAware(true),这个配置必须在创建builder之前设置才会生效。配置顺序错误导致DOM解析时没有保留命名空间信息,doc.lookupNamespaceURI("ns3")返回空值,XPath解析时自然找不到ns3对应的命名空间,抛出异常。 - 第二,XPath表达式存在拼写错误:你写的路径是
/ns3:receive/infor/answer/...,但XML里的对应节点名是info,多写了一个字母r,就算命名空间问题解决也查不到结果。 - 第三,默认命名空间未处理:
info、answer这些节点都属于xmlns="http://xxx/"的默认命名空间,你没有在XPath里给这些节点加对应前缀匹配,就算路径拼写正确也查不到节点。
修复代码
首先修正XML解析方法的配置顺序:
private static Document convertStringToXMLDocument(String xmlString) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 必须在创建DocumentBuilder之前设置命名空间感知 factory.setNamespaceAware(true); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(xmlString))); return doc; } catch (Exception e) { e.printStackTrace(); } return null; }
再修正主逻辑的命名空间映射和XPath表达式,建议直接显式声明命名空间映射,避免依赖DOM lookup的兼容性问题:
public void function() { try { final Document doc = convertStringToXMLDocument( serviceResponse ); XPath xPath1 = XPathFactory.newInstance().newXPath(); xPath1.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { // 显式映射前缀,兼容性更强 if ("ns3".equals(prefix)) { return "urn:xxx:xxx:xxx:xxx:xxx"; } // 给默认命名空间自定义前缀def if ("def".equals(prefix)) { return "http://xxx/"; } return javax.xml.XMLConstants.NULL_NS_URI; } @Override public String getPrefix(String namespaceURI) { return null; } @Override public Iterator getPrefixes(String namespaceURI) { return null; } }); // 修正拼写错误,给默认命名空间下的节点加def前缀 Node errorcode = (Node) xPath1.evaluate("/ns3:receive/def:info/def:answer/def:errorstructure[1]/def:errorid/text()", doc, XPathConstants.NODE); if (errorcode != null) { LOGGER.info("TESTING ERROR CODE : " + errorcode.getNodeValue()); } } catch (Exception e) { e.printStackTrace(); serviceResponse = e.getMessage(); } }
内容的提问来源于stack exchange,提问作者Buster3650
相关产品推荐
相关产品推荐

