views:

174

answers:

2

Hi all:

I've found a similar question on SO, however, that seems not exactly what I wanna achieve:

Say, this is a sample XML file:

<root>
    <item>
        <id isInStock="true">10001</id>
        <category>Loose Balloon</category>
    </item>
    <item>
        <id isInStock="true">10001</id>
        <category>Bouquet Balloon</category>
    </item>
    <item>
        <id isInStock="true">10001</id>
        <category>Loose Balloon</category>
    </item>
</root>

If I wanna get a "filtered" subset of the item elements from this XML, how could I use an XPath expression to directly address that?

XPathExpression expr = xpath.compile("/root/item/category/text()");

I now know this would evaluate to be the collection of all the TextContent from the categories, however, that means I have to use a collection to store the values, then iterate, then go back to grab other related info such as the item id again.

Another question is : how could I refer to the parent node properly?

Say, this xpath expression would get me the collection of all the id nodes, right? But what I want is the collection of item nodes:

XPathExpression expr = xpath.compile("/root/item/id[@isInStock='true']");

I know I should use the "parent" axis to refer to that, but I just cannot make it right...

Is there a better way of doing this sort of thing? Learning the w3cschools tutorials now...

Sorry I am new to XPath in Java, and thanks a lot in advance.

+1  A: 

To select the item, You can continue the path after the predicate to jump back to the parent of the found id(s)

XPathExpression expr = xpath.compile("/root/item/id[@isInStock='true']/../text()");

When you evaluate this, it should return a NodeList containing the filtered item Nodes (and their subtrees), which you can then iterate through.

Matthew Flynn
@Matthew Flynn : ahhh, that is the only case I didn't try myself... Thanks for the answer
Michael Mao
Oops--I just edited my original answer while you were replying. My first response was incorrect, actually (I tried it). What's there now works.
Matthew Flynn
@Matthew Flynn : thanks for this. I am absolutely new to XPath so I got errors all the time :) Now I see the logic behind the expression much clearer.
Michael Mao
+2  A: 

If I wanna get a "filtered" subset of the item elements from this XML, how could I use an XPath expression to directly address that?

An example XPath expression:

/*/item[id/@isInStock='true']/category/text()

This XPath expression selects all text-node children of all <category> elements of all <item> elements the isInStock attribute of whose id child has a value of 'true' and (the id elements) that are children of the top element of the XML document.

Another question is : how could I refer to the parent node properly?

Use:

parent::node()

or simply

..

Dimitre Novatchev
@Dimitre Novatchev : Thanks for the answers, I now see the expression more like a query now. Frankly speaking, it is very interesting to know a query/address expression targeting xml(tree), similar to that of jQuery's, but not quite :)
Michael Mao
@Michael-Mao: The best way of learning XPath that I can recommend is by using my own XPath Visualizer.
Dimitre Novatchev
@Dimitre Novatchev : this? http://xpathvisualizer.codeplex.com/ Quite a nice one, reminding me of the jQuery selector visualizer :)
Michael Mao
No, mine is the *classic* Xpath Visualizer (first produced in year 2000, which is at www.topxml.com. However, this site was abandoned by its maintainers and now contains trojans (do not try to access it!). If interested, ask me at dnovatchev at google's email domain and I'll send it to you.
Dimitre Novatchev