JAVA和XML:com.sun.org.apache.xpath.internal.XPathException:无法将#STRING转换为NodeList

时间:2018-07-17 22:44:44

标签: java xml xpath

我正在编写一个Java函数,该函数解析xml元素并提取给定的xpath表达式。下面是函数:

public static Node getDataNode(Element payload, final HashMap<String, String> namespaces, String xpathStr) {
    Node node = null;
    try {
        // Create a namespace context based on the namespaces passed in.
        NamespaceContext ctx = new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                return namespaces.get(prefix);
            }

            public Iterator getPrefixes(String val) {
                return null;
            }

            public String getPrefix(String uri) {
                return null;
            }
        };
        XPathFactory xpathFact = XPathFactory.newInstance();
        XPath xpath = xpathFact.newXPath();
        xpath.setNamespaceContext(ctx);
        XPathExpression expr = xpath.compile(xpathStr);
        System.out.println("Got request to process node : " + payload.getLocalName() + " with " + xpathStr);
        System.out.println(xpathStr + " has been compiled successfully.");
        ((XMLElement) payload).print(System.out);
        node = (Node) expr.evaluate(payload, XPathConstants.NODE);
    } catch (XPathExpressionException ex) {
        ex.printStackTrace();
        return null;
        } catch (IOException io) {
            io.printStackTrace();
            return null;
        }
    return node;
}

以下是该功能部分的日志:

Got request to process node : Body with ".//soapenv:Body/pip:request"
".//soapenv:Body/pip:request" has been compiled successfully.
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <pip:request xmlns:pip="http://xmlns.oracle.com/ServiceBusApplication/UserInterfaceTest/Pipeline">textContent</pip:request>
   </soapenv:Body>

我尝试了不同的xpath表达式,例如//soapenv:Body/pip:request、.//soapenv:Body/pip:request,但仍然出现错误:

com.sun.org.apache.xpath.internal.XPathException: Can not convert #STRING to a NodeList!
  at com.sun.org.apache.xpath.internal.objects.XObject.error(XObject.java:711)
  at com.sun.org.apache.xpath.internal.objects.XObject.nodeset(XObject.java:441)
  at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.getResultAsType(XPathExpressionImpl.java:357)
  at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:101)
  at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:182)

请让我知道代码中有什么问题。感谢您为解决问题提供的帮助。谢谢。

1 个答案:

答案 0 :(得分:0)

无法复制。在Oracle JDK 1.5和Oracle JDK 9上使用下面的MCVE代码进行了测试。

由于Oracle JDK没有getDataNode类型,因此仅对((XMLElement) payload).print(System.out)方法所做的更改会注释掉XMLElement语句。

测试

import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
String xml = "<soapenv:Body xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
             "      <pip:request xmlns:pip=\"http://xmlns.oracle.com/ServiceBusApplication/UserInterfaceTest/Pipeline\">textContent</pip:request>\n" +
             "   </soapenv:Body>";
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
Document document = domBuilder.parse(new InputSource(new StringReader(xml)));

HashMap<String, String> namespaces = new HashMap<String, String>();
namespaces.put("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
namespaces.put("pip", "http://xmlns.oracle.com/ServiceBusApplication/UserInterfaceTest/Pipeline");

Node node = getDataNode(document.getDocumentElement(), namespaces, ".//soapenv:Body/pip:request");
System.out.println(node != null ? node.getTextContent() : null);

node = getDataNode(document.getDocumentElement(), namespaces, "/soapenv:Body/pip:request");
System.out.println(node != null ? node.getTextContent() : null);

node = getDataNode(document.getDocumentElement(), namespaces, ".//pip:request");
System.out.println(node != null ? node.getTextContent() : null);

输出

Got request to process node : Body with .//soapenv:Body/pip:request
.//soapenv:Body/pip:request has been compiled successfully.
null
Got request to process node : Body with /soapenv:Body/pip:request
/soapenv:Body/pip:request has been compiled successfully.
textContent
Got request to process node : Body with .//pip:request
.//pip:request has been compiled successfully.
textContent

如您所见,代码运行良好,但是.//soapenv:Body/pip:request XPath对于给定的XML不正确,因为在给定的{{里面没有<soapenv:Body>标记 1}}元素。