如何将XPath评估范围缩小到单个节点而不是Java中的整个文档?

时间:2015-04-21 16:13:54

标签: java xml xpath

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代码输出以下文本:

> CCC
> CCC2
...

以下是我编写的用于产生预期结果的代码:

Java代码

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

XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//i");

NodeList listOfiNodes = (NodeList) expr.evaluate(d, XPathConstants.NODESET);

for(int i=0;i<listOfiNodes.getLength();i++) {
    XPathExpression expr2 = xpath.compile("//c");
    System.out.println("> " + ((Node) expr2.evaluate(listOfiNodes.item(i), XPathConstants.NODE)).getTextContent());   
}

expr2继续返回第一个c节点。所以我得到了这个输出:

> CCC
> CCC
...

expr2执行的评估似乎并没有停留在&#34;在传递给evaluate()方法的节点上。为什么呢?

NOTA:我不想直接使用xpath c(或//i/c)获取/l/i/c个节点。

Java 6

2 个答案:

答案 0 :(得分:1)

//c选择整个文档中的所有匹配节点。请改用c,您将收到此输出:

> CCC
> CCC2

请注意,如果节点i在打印结果的行中不包含c,您将获得NPE。以下代码应按预期工作:

DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document d = docBuilder.parse("stream.xml");

XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//i");

NodeList listOfiNodes = (NodeList) expr.evaluate(d, XPathConstants.NODESET);

for (int i = 0; i < listOfiNodes.getLength(); i++) {
    javax.xml.xpath.XPathExpression expr2 = xpath.compile("c");
    Node item = listOfiNodes.item(i);
    Node node = (Node) expr2.evaluate(item, XPathConstants.NODE);
    if (null != node) {
        System.out.println("> " + node.getTextContent());
    }
}

答案 1 :(得分:1)

使用"//c"

更改".//c"
XPathExpression expr2 = xpath.compile(".//c");

它将从当前节点的任何地方开始搜索而不是整个文档。

    XPathExpression expr2 = (XPathExpression) xpath.compile(".//c");
    for(int i=0;i<listOfiNodes.getLength();i++) {
        System.out.println("> " + ((Node) expr2.evaluate(listOfiNodes.item(i), XPathConstants.NODE)).getTextContent());   
    }

输出:

  

CCC
  CCC2