【问题标题】:How to call the XPath position() function in Java?如何在 Java 中调用 XPath position() 函数?
【发布时间】:2015-04-20 15:16:38
【问题描述】:

这是我的 XML 代码:

test.xml

<l>
    <i>
        <a>AAA</a>
        <b>BBB</b>
        <c>CCC</c>
    </i>
    <i>
        <a>AAA2</a>
        <b>BBB2</b>
        <c>CCC2</c>
    </i>
    <i>
        ...
    </i>
</l>

我想用 Java 提取第二个 c 节点。我尝试了以下代码:

test.java

DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document d = docBuilder.parse("file:///C:/path/to/my/test.xml");

XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//c[position()=2]");

// The following line raises a NPE
System.out.println("> " + ((Node) expr.evaluate(d, XPathConstants.NODE)).getTextContent());

但是evaluate 方法返回空值,因此引发了 NullPointerException (NPE)。

我错过了什么?

Java 6

【问题讨论】:

    标签: java xml xpath


    【解决方案1】:

    发生的情况是:XPath 中的位置谓词通常应用于输入树的节点,而不是中间结果序列。 XPath 表达式,如

    //c[position() = 2]       |   or //c[2]
    

    意思是:

    选择输入文档中任意位置的所有元素节点c,如果它们是其父元素的第二个c 子元素

    现在让我们看看您的输入文档:

    <l>
        <i>
            <a>AAA</a>
            <b>BBB</b>
            <c>CCC</c>
        </i>
        <i>
            <a>AAA2</a>
            <b>BBB2</b>
            <c>CCC2</c>
        </i>
        <i>
            ...
        </i>
    </l>
    

    其中的两个c 元素都是其父元素的第一个 c 子元素,这就是结果集为空的原因。

    打算做的是

    • 第一步,查找输入文档中存在的所有c 元素
    • 仅将这些节点中的 置于中间结果序列中

    这正是//c 周围的括号的作用:

    (//c)[2]
    

    如果我运行 //i[position()=2],我只会得到第二个 i。

    实际上一个i 元素在输入中,它是其父元素的第二个i 子元素。但是,这个表达式并不总是返回单个项目。如果您的输入文档的结构是这样的

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <l>
            <i>
                <a>AAA</a>
                <b>BBB</b>
                <c>CCC</c>
            </i>
            <i>
                <a>AAA2</a>
                <b>BBB2</b>
                <c>CCC2</c>
            </i>
            <i>
                ...
            </i>
        </l>
        <l>
            <i>
                <a>AAA</a>
                <b>BBB</b>
                <c>CCC</c>
            </i>
            <i>
                <a>AAA2</a>
                <b>BBB2</b>
                <c>CCC2</c>
            </i>
            <i>
                ...
            </i>
        </l>
    </root>
    

    那么//i[2] 将返回两个 i 元素。

    【讨论】:

    • //c[2] 返回文档中的所有 c 元素,它们是其各自父项中的 第二个 c,而不是 第二个子项。示例输入中的所有 c 元素都是其父元素中的 first c,这就是 //c[2] 不返回任何内容的原因 - 文档中没有“第二个 c”元素。
    • @IanRoberts 这就是我的意思——但应该更清楚,我同意。我会编辑答案。
    • @IanRoberts 感谢您的评论,那部分实际上是完全错误的 - 我现在已经更正了。
    【解决方案2】:

    [] 运算符的优先级高于导致问题的//。使用

    (//c)[position()=2]
    

    相反,当我尝试时解决了问题。

    【讨论】:

    • 这个“更高的优先级”从何而来?
    • 此链接列出了 XPath 1 中的所有运算符,以及优先级 safaribooksonline.com/library/view/xslt-2nd-edition/…
    • 如果我运行//i[position()=2],我只会得到第二个i
    • @Stephan 是的,但原因不是你想的那样。看我的回答。
    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多