Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javax.xml中,XPath不是从具有名称空间的xml中提取的_Java_Xml_Xpath - Fatal编程技术网

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

在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

有“原始”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("/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节点不是好的设计,对吗?