javax.xml,XPath不是从带有名称空间的XML中提取的

有“原始”XML

   555      172799999 555 carbon    

以这种方式解析XML

 // javax.xml.parsers.* DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(pathToXml); 

然后我试图通过XPath提取会话ID

 // javax.xml.xpath.*; XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); // next xpath does not work with Java and online xpath tester //XPathExpression expr = xpath.compile("/soap:Envelope/soap:Header/context/session/text()"); // this xpath works with online xpath tester but does not with in Java XPathExpression expr = xpath.compile("/soap:Envelope/soap:Header/*[name()='context']/*[name()='session']/text()"); String sessionId = (String)expr.evaluate(doc, XPathConstants.STRING); 

在这里测试http://www.xpathtester.com/xpath/678ae9388e3ae2fc8406eb8cf14f3119

当XML简化为此时

  
555
172799999 555 carbon

这个XPath完成它的工作

 XPathExpression expr = xpath.compile("/Envelope/Header/context/session/text()"); 

如何使用Java从“原始”XML中提取会话ID?

更新:JDK 1.6

答案是您需要正确使用名称空间和名称空间前缀 :

首先,在使用之前通过调用它来使您的DocumentBuilderFactory命名空间可识别:

 factory.setNamespaceAware(true); 

然后执行此操作以检索所需的值:

 XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if (prefix.equals("soap")) { return "http://www.w3.org/2003/05/soap-envelope"; } if (prefix.equals("zmb")) { return "urn:zimbra"; } return XMLConstants.NULL_NS_URI; } @Override public String getPrefix(String namespaceURI) { throw new UnsupportedOperationException("Not supported yet."); } @Override public Iterator getPrefixes(String namespaceURI) { throw new UnsupportedOperationException("Not supported yet."); } }); XPathExpression expr = xpath.compile("/soap:Envelope/soap:Header/zmb:context/zmb:session"); String sessionId = (String)expr.evaluate(doc, XPathConstants.STRING); 

您可能需要在文件的开头添加一行以导入NamespaceContext类:

 import javax.xml.namespace.NamespaceContext; 

http://ideone.com/X3iX5N

你总是可以通过忽略命名空间来做到这一点,而不是理想的方法但是有效。

  "/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='context']/*[local-name()='session']/text()"