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;
你总是可以通过忽略命名空间来做到这一点,而不是理想的方法但是有效。
"/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='context']/*[local-name()='session']/text()"