首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >javax.xml,XPath不是从带有名称空间的XML中提取的。

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

Stack Overflow用户
提问于 2014-04-21 18:27:58
回答 2查看 1.1K关注 0票数 0

有“原始”XML

代码语言:javascript
复制
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Header>
        <context xmlns="urn:zimbra">
            <session id="555">555</session>
            <change token="333"/>
        </context>
    </soap:Header>
    <soap:Body>
        <AuthResponse xmlns="urn:zimbraAccount">
            <lifetime>172799999</lifetime>
            <session id="555">555</session>
            <skin>carbon</skin>
        </AuthResponse>
    </soap:Body>
</soap:Envelope>

XML是以这种方式解析的。

代码语言:javascript
复制
// javax.xml.parsers.*
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(pathToXml);

然后我尝试提取XPath的会话id

代码语言:javascript
复制
// 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简化为以下内容时

代码语言:javascript
复制
<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>

这个XPath完成了它的工作

代码语言:javascript
复制
XPathExpression expr = xpath.compile("/Envelope/Header/context/session/text()");

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

更新: JDK 1.6

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-21 18:43:11

答案是你需要correctly use namespaces and namespace prefixes

首先,在使用DocumentBuilderFactory名称空间之前调用它,从而使其意识到:

代码语言:javascript
复制
factory.setNamespaceAware(true); 

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

代码语言:javascript
复制
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类:

代码语言:javascript
复制
import javax.xml.namespace.NamespaceContext;

http://ideone.com/X3iX5N

票数 2
EN

Stack Overflow用户

发布于 2014-04-22 05:38:51

您可以始终通过忽略命名空间来完成这一任务,这不是理想的方法,而是有效的。

代码语言:javascript
复制
 "/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='context']/*[local-name()='session']/text()"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23203421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档