【问题标题】:Unable to evaluate expression in XPath无法计算 XPath 中的表达式
【发布时间】:2013-05-14 22:37:09
【问题描述】:

我正在使用 XPath 解析由 URL 返回的 XML 文档,当我使用给定的输入运行我的代码时,它可以工作,但是当它作为用户输入提供输入时,它会引发异常。 守则:

    class{
        private String generalQuery =  "//@*";
    method(){
        System.out.println("Enter URL");
        url = scan.nextLine();
        URL oracle = new URL(url);
        InputStream is = oracle.openStream();

        org.w3c.dom.Document doc = null;
        DocumentBuilderFactory domFactory;
        DocumentBuilder builder;

        try {
            domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            builder = domFactory.newDocumentBuilder();
            doc = builder.parse(is);
        } catch (Exception ex) {
            System.err.println("unable to load XML: " + ex);
        }

    Map <String, String> params = new HashMap<String, String> ();

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            xpath.setNamespaceContext(new NameSpaces(doc));
            XPathExpression expr = xpath.compile(generalQuery);
            Object result = expr.evaluate(doc, XPathConstants.NODESET); // exception thrown here

            NodeList nl = (NodeList) result;

            for (int i = 0 ; i < nl.getLength() ; i++){
                Node n = (Node)nl.item(i);
                params.put(n.getNodeName(), n.getNodeValue());
            }

            return params;
}
}

例外情况:

javax.xml.transform.TransformerException: Unable to evaluate expression using this context

类命名空间:

import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Document;

public class NameSpaces implements NamespaceContext {
    private Document sourceDocument;

    public NameSpaces(Document document) {
        sourceDocument = document;
    }

    @Override
    public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
            return sourceDocument.lookupNamespaceURI(null);
        } else {
            return sourceDocument.lookupNamespaceURI(prefix);
        }
    }

    @Override
    public String getPrefix(String namespaceURI) {
        return sourceDocument.lookupPrefix(namespaceURI);
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        return null;
    }
}

【问题讨论】:

  • 这段代码sn-p中doc的类型是什么?
  • 它是由dom创建的XML文档
  • 什么是NameSpacessetNamespaceContext 方法需要 NamespaceContext 类型的参数。正如@Ian 指出的那样,您也没有告诉我们doc 的类型。如所写,您的问题甚至无法编译,您让我们猜测您应该包含的内容。
  • 我用您可能需要的所有信息编辑了问题

标签: java xml exception xpath transformer


【解决方案1】:

尝试评估 XPath 表达式时,null 文档也可能导致异常“无法使用此上下文评估表达式”。 (我遇到了同样的错误,我花了一段时间才发现我没有正确初始化我的文档)。

在你的代码中

try {
  // load document
}
catch (Exception ex) {
  System.err.println("unable to load XML: " + ex);
}

// happily continue

这是自找麻烦。如果在初始化期间发生异常,您应该立即停止并且不应该继续。如果您完全不知道如何处理错误,请使用catch(Exception e) { throw new Error(e); }。这将导致异常冒泡,并希望由打印堆栈跟踪并退出的默认异常处理程序处理。

作为您问题的读者,我什至不知道异常是在哪里引发的。您应该提供这些信息。请注意,您还可以使用someException.printStackTrace(); 来获取指向正确行的堆栈跟踪。

【讨论】:

  • 是的,在我的情况下,错误是由于文档为空。这是上游错误的结果。谢谢。
【解决方案2】:

您似乎缺少的是可以自己实现的NameSpaceContext

另请参阅此主题:NamespaceContext and using namespaces with XPath

例子:

class NamespaceResolver implements NamespaceContext {

    private final Document document;

    public NamespaceResolver(Document document) {
        this.document = document;
    }

    public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
            return document.lookupNamespaceURI(null);
        } else {
            return document.lookupNamespaceURI(prefix);
        }
    }

    public String getPrefix(String namespaceURI) {
        return document.lookupPrefix(namespaceURI);
    }

    @SuppressWarnings("rawtypes")
    public Iterator getPrefixes(String namespaceURI) {
        // not implemented
        return null;
    }

}

然后你像这样启动 XPath 实例:

    getXPath().setNamespaceContext(new NamespaceResolver(doc));

【讨论】:

  • 可能是对的,但 OP 并没有真正包含足够的信息来确定。
  • 我已经做到了,类 NameSpaceResolver 的名称只是我代码中的 NameSpaces
  • @Brass Block:也许您也可以向我们展示 XML。 xml 是否有正确的命名空间声明?
【解决方案3】:

在我的情况下,这不是由于 null 文档,而是由于没有根元素的 empty 文档。附加后者解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多