当XPath使用前一个兄弟轴时,我想以相反的顺序返回节点?怎么样 ?

时间:2012-05-11 10:00:59

标签: java xml xpath xml-parsing

给出以下XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stock SYSTEM "new.dtd">
<stock>
    <book num="myBook1">
        <title>Lindsy Boxer</title>
        <author>James Patterson</author>
        <publisher>LittleBig</publisher>
        <price>18.21</price>
        <chapter>
            <title>Alex Cross Is Back - Chapter A</title>
            <paragraph>
                This is the <emph>first</emph> paragraph.
                <image file="alexCrossImage.gif"/>
                afetr image...
            </paragraph>
            <paragraph>
                This is the <emph>second</emph> paragraph.
                <image file="alexCrossImageAnother.gif"/>
                afetr image...
            </paragraph>
        </chapter>
        <chapter>
            <title>Along Came A Spider - Chapter B</title>
            <section>
                <title>Along Came A Spider - Chapter B - section 1</title>
                <paragraph>
                    This is the <emph>first</emph>paragraph for chapter TWO section ONE.
                    <image file="Chapter_B_firstParagraphImage.gif"/>
                    afetr image...
                </paragraph>
                <paragraph>
                    This is the <emph>second</emph> paragraph for chapter TWO section ONE.
                    <image file="Chapter_B_secondParagraphImage.gif"/>
                    afetr image...
                </paragraph>
            </section>
        </chapter>
        <chapter>
            <title>Chapter C</title>
            <paragraph>
                This chapter has no images and only one paragraph
            </paragraph>
        </chapter>
    </book>
    <book num="myBook2">
        <title>Jack Reacher Series</title>
        <author>Lee Child</author>
        <author>Jonny White</author>
        <publisher>Pocket</publisher>
        <price>5.99</price>
        <chapter>
            <title>Jack Reacher - Chapter ONE</title>
        </chapter>
        <chapter>
            <title>Jack Reacher - Chapter TWO</title>
            <paragraph>
                This is the <emph>second</emph> paragraph of SECOND book chapter TWO.
                <image file="Jack_Reacher_Picture_Top_Sniper_US_Army.gif"/>
                afetr image...
            </paragraph>
        </chapter>
    </book>
    <book num="myBook3">
        <title>Alex Cross - Double Cross</title>
        <author>James Patterson</author>
        <publisher>Spectra</publisher>
        <price>17.30</price>
        <chapter>
            <title>Alex Cross - Double Cross - Chapter A</title>
        </chapter>
    </book>
</stock>

当我输入以下查询时:

Object myQuery= xpath.evaluate("stock/book/chapter[3]/preceding-sibling::chapter//title",doc,XPathConstants.NODESET);

我得到的输出为:

<title>Alex Cross Is Back - Chapter A</title>
<title>Along Came A Spider - Chapter B</title>
<title>Along Came A Spider - Chapter B - section 1</title>

但我想要的是当我的XPath使用前一个兄弟轴时,我想返回节点 相反的顺序,即:

         *  <title>Along Came A Spider - Chapter B</title>
         *  <title>Along Came A Spider - Chapter B - section 1</title>
         *  <title>Alex Cross Is Back - Chapter A</title>

基本上,正如您所看到的,Java按照XML文件中节点的顺序以混合顺序返回节点,但我需要的是,当XPath使用前一个兄弟轴时,然后返回节点以相反的顺序。

这不是发生这种“行为”的唯一命令(返回混合节点)。

我的目标是解决这个问题,我尝试更改XPath's evalute,但它仍然不起作用。

任何人都可以提供一些指示/提示如何做到这一点?

P.S

使用这段代码:

        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); // never forget this!
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse("new.xml");
        //create an XPath factory
        XPathFactory factory = XPathFactory.newInstance();
        //create an XPath Object
        XPath xpath = factory.newXPath();
        //***********************************************************//
        Object myQuery= xpath.evaluate("stock/book/chapter[3]/preceding-sibling::chapter//title",doc,XPathConstants.NODESET);
        System.out.println("The Results are:");
        NodeList nodes = (NodeList) myQuery;
        //print the output
        for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println("i: " + i);
            System.out.println("*******");
            System.out.println(nodeToString(nodes.item(i)));
            System.out.println("*******");
        }

我得到了上面的结果(混合节点)

2 个答案:

答案 0 :(得分:3)

您希望按照不是文档顺序的顺序返回选定的节点。

今天的XPath 1.0引擎无法实现这一点 - 所有这些都按文档顺序返回选定的节点。并且XPath 1.0没有指定任何特殊订单的方法。

因此,如果您正在使用XPath 1.0(似乎就是这种情况),您将不得不忍受 - 例如索引结果不是增加索引而是减少索引。

在XPath 2.0中有序列,您可以编写XPath表达式并指定序列中的每个项目

或者(再次在XPath 2.0中)你可以拥有:

reverse(yourExpression)

这将产生相反的项目序列 - 由yourExpression生成的项目序列。

答案 1 :(得分:1)

实际上这不是'混合'顺序。这只是XPath执行Breadth-first search的结果。正如我所见,你需要一个Depth-first search。 DFS结果就像一个简单的搜索结果 - 在文档中首先出现的结果将出现在搜索结果的前面。

您可以尝试使用StAX - 一个流阅读器来实现它。这不是DFS,而是普通的XML阅读器,它可以为您提供所需的结果。