在javax.xml中,XPath不是从具有名称空间的xml中提取的
有“原始”XML 然后我尝试通过XPath提取会话id在javax.xml中,XPath不是从具有名称空间的xml中提取的,java,xml,xpath,Java,Xml,Xpath,有“原始”XML 然后我尝试通过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("/so
// 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);
在这里测试
当XML简化为这样时
<Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<Header>
<context>
<session id="555">555</session>
<change token="333"/>
</context>
</Header>
<Body>
<AuthResponse xmlns="urn:zimbraAccount">
<lifetime>172799999</lifetime>
<session id="555">555</session>
<skin>carbon</skin>
</AuthResponse>
</Body>
</Envelope>
如何使用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;
答案是你需要: 首先,在使用
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()"
您总是可以通过忽略名称空间来实现这一点,虽然这不是理想的方法,但仍然有效
"/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='context']/*[local-name()='session']/text()"
嗨,JLRishe,不幸的是这对我不起作用。顺便说一句,我必须使用JDK1.6。
NamespaceContext
似乎可以从JDK1.5开始使用:当我提到JDK1.6时,我暗示“switch”构造不适用于字符串对象类型。但这是微不足道的。“这不起作用”-这意味着当我用“if->return,if->return”替换开关时,在XPathExpression求值之后,sessionId是空的。甚至当我试图在XPath的末尾添加“/text()”或“/@id”时,sessionId仍然是空的。好吧,经过20分钟的挫折之后,我终于想起了DocumentBuilderFactory
具有忽略名称空间的恼人行为,除非你告诉它注意它们。请看我在上面编辑的答案。现在像一个符咒一样工作:-)。非常感谢。嗨,JLRishe,不幸的是这对我不起作用。顺便说一句,我必须使用JDK1.6。NamespaceContext
似乎可以从JDK1.5开始使用:当我提到JDK1.6时,我暗示“switch”构造不适用于字符串对象类型。但这是微不足道的。“这不起作用”-这意味着当我用“if->return,if->return”替换开关时,在XPathExpression求值之后,sessionId是空的。甚至当我试图在XPath的末尾添加“/text()”或“/@id”时,sessionId仍然是空的。好吧,经过20分钟的挫折之后,我终于想起了DocumentBuilderFactory
具有忽略名称空间的恼人行为,除非你告诉它注意它们。请看我在上面编辑的答案。现在像一个符咒一样工作:-)。非常感谢。谢谢Sean F,您的解决方案确实有效。我认为在同一级别上使用相同名称但具有不同名称空间的两个XML节点不是很好的设计,对吗?谢谢Sean F,您的解决方案确实有效。我认为在同一级别上具有相同名称但具有不同名称空间的两个XML节点不是好的设计,对吗?