XPath 编译行为

XPath compiling behaviour

我正在测试我的应用程序,发现编译时行为有所不同。

例如,如果我要编译的表达式是:

XPathExpression expr = xPath.compile("/DocDetails/TransactionSignature");

并且:

XPathExpression expr2 = xPath.compile("/DocDetails/" + x); 

x 被声明为字符串数据类型。

假设 expr2 中的 x 是 "abc",XPathExpression 编译没有问题。

但是如果 expr2 中的 x 是“123abc”或“123”,XPathExpression 会抛出一个:

javax.xml.transform.TransformerException: A location step was expected following the '/' or '//' token.

只是对这种行为感到好奇..

完整代码供参考:

        String document = "C:/Users/Eunice/Documents/MITS/doc.xml";
        String document2 = "C:/Users/Eunice/Documents/MITS/doc2.xml";

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(document);

        Document doc2 = builder.parse(document2);

        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();
        XPathExpression expr = xPath.compile("/DocDetails/TransactionSignature");
        Node node = (Node)expr.evaluate(doc, XPathConstants.NODE);

        String x = node.getTextContent();

        System.out.println(x);

        XPathExpression expr2 = xPath.compile("/DocDetails/" + x);
        Node node2 = (Node)expr2.evaluate(doc2, XPathConstants.NODE);

        if (node2 == null)
            System.out.println("null");
        else 
            System.out.println("not null " + node2.getTextContent());

这是 XML 文件:

<DocDetails>
    <TransactionSignature>abc123</TransactionSignature>
</DocDetails>

But if x in expr2 is "123abc" OR "123", XPathExpression throws a

XML 元素名称不能以数字开头。因此你的例子相当于

XPathExpression expr2 = xPath.compile("/DocDetails/123abc");

我猜 XPath 解析器不期望它。

您还应该提供完整的 XML。我相信它肯定不包含 <DocDetails><TransactionSignature>abc123</TransactionSignature><123abc>something</123abc></DocDetails> 之类的内容。这简直是​​无效的XML.

找了好久终于找到答案了!

以数字开头的元素标签实际上是非法的。

可见this Whosebug answer

最初,这一行抛出一个转换器异常:

        XPathExpression expr2 = xPath.compile("/DocDetails/" + x); 

由于以数字开头是非法的,他们可能会将其视为无效标签。

这意味着这一行实际上是读取“/DocDetails/”而不是“/DocDetails/123”或“/DocDetails/123abc”,

在最后导致额外的“/”,因此抛出转换器异常。