当前位置: 首页 > 面试题库 >

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

霍永年
2023-03-14
问题内容

有“原始” XML

<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

// 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简化为此

<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可以完成工作

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



 类似资料:
  • 问题内容: 我有下一个XML: 如何获得此节点?我试过了 但它返回一个空数组。我该怎么做? 问题答案: 您需要确保XML解析器支持名称空间。 您还应该确保关闭,最好使用try-with-resources。

  • 问题内容: 我想获取标记之间的所有内容,但是由于urn:名称空间,我不知道该怎么做。 有任何想法吗? 问题答案: 简短的答案:使用XPath 。这样:将返回 或者,您可以实现一个映射名称空间名称和URI的,并在查询之前在XPath对象上对其进行设置。 看一下这篇博客文章, 更新: 该文章已结束,您可以在webarchive上看到它 解决方案1样本: 解决方案2样本: 编辑 这是一个完整的示例,它可

  • 问题内容: 我得到了以下XML: 跟随XPath不起作用意味着没有任何打印内容,例如“ data”元素不存在: /root/items/item/details/data 但是,当我删除“数据”元素的“ xmlns”名称空间属性时,将打印其内容。在不删除“数据”元素的“ xmlns”命名空间属性的情况下,xpath表达式应该如何工作? 我正在使用SAXON和XSL 1.0。 问题答案: 这是XPa

  • 我需要加载XML文件,但存在两种相同的文件格式,只是名称空间不同-在我的简化示例中,: : 引用了一个特定的名称空间,因此我不能以相同的方式处理这两个文件: 给出输出: 目前,我已经以一种次优的方式进行了工作,通过使用https://stackoverflow.com/a/50800021-但如果可能的话,我想将其转移到JAXB中。 输出:

  • 问题内容: 我正在做这个小项目,我的任务是读取xml文件并进行解析,以便可以将其存储在类中。这是xml示例。它是用SOAP编写的,我要做的就是获取 xmlns:ns2="http://abc.examples.com 问题答案: 要使用Java中的命名空间进行XPath查询,我相信您需要执行以下操作: 您还需要先调用;,然后再创建来解析文档。

  • 使用xslt 1.0(BizTalk 2016)我正在寻找一种通用的方法来选择任何有效的xml文档的命名空间 例如,我有以下xml文档: 假设根元素的值可以是任何东西,那么选择名称空间值的xpath是什么http://www.random.com/bo/request/portfolioactivation 我原本希望“/*/@xmlns”能起作用,但事实并非如此。