tags:

views:

177

answers:

3

So to expand...

I have some XML

<root>
    <list>
        <item value="9"/>
        <item value="3"/>
        <item value="1"/>
        <item value="8"/>
        <item value="4"/>
    </list>
</root>

I have an XPath "/root/list/item [4]" which I believe will retrieve the 5th 'item' element (whose value attribute is 4)

This suggests that the XPath "/root/list/item [5]" will reference the (as yet non existent) 6th item.

What I would like is an XPath expression which will reference the 'Next' (as yet non-existant) 'item' element regardless of how many items there are currently...

I assume that this will pass an expression (which will count the number of current elements) rather than a hard coded number.

I know how I would do it, but simply cannot find how I should do it... frustrating.

Update: To clarify... I would like to return "the item node after the last item node". the attributes were there just to distinguish the existing nodes). I appreciate that this will return an empty nodeset.

Update: Well I have my answer so I guess it's only fair I explain why I wanted this :)

Basically the xPath is used by some .Net code as a write address rather than a read address.

I pass the xPath of a non existent location to an EnsureNodeExists routine. (Note: I cannot alter this EnsureNodeExists routine) The code will iterate each element of the xPath, creating it if it's not there and then setting it as the parent for the next iteration.

Thus I can call this code with "/root/list/item[position() = last()]/following-sibling::item[1]" 3 times and this will result in 3 item nodes being created.

+4  A: 

First off, your XPath:

/root/list/item[4]

fetches the fourth item (since the [4] predicate is a shorthand for [position() = 4]).

To fetch the item with @value 4, use:

/root/list/item[@value = '4']

if you want to fetch the item after the item with @value 4, use:

/root/list/item[@value = '4']/following-sibling::item[1]

This translates to English as "going from the /root/list/item with @value = '4', look at the following siblings named 'item' and take the first one".

This works even if there is no following item. In this case the selected node set will be empty.

EDIT: Be aware that the results the above expression produces may be unexpected if there is more than one item with value 4. You will get all items that follow an item with value four. This will return one item at maximum:

/root/list/item[@value = '4'][1]/following-sibling::item[1]

To refer to the last node in a list, use:

/root/list/item[position() = last()]

A nice visual that explains the XPath axes can be found here: http://nwalsh.com/docs/tutorials/xsl/xsl/graphics/axes.gif (part of a larger tutorial).

Tomalak
Ok I think I've confused the issue by using the attributes... I want to return the item after the last item. (I appreciate that this will be an empty nodeset).
Rory Becker
So based on your answer I'm after ....."/root/list/item[position() = last()]/following-sibling::item[1]"... which should get me the 8th item in a list of 7 or the 101th item in a list of 100?
Rory Becker
Yes, in theory. BUT - there is no item after the last item. Never. What do you think this buys you? :-)
Tomalak
I am using the xPath as a write address rather than as a read address... See update above.
Rory Becker
/root/list/item[last()] is shorter ;-)
Azat Razetdinov
That's true. ;-)
Tomalak
+1  A: 

try the following-sibling expression

help with this sort of thing can be found here

darasd
+3  A: 

If you just want an expression to return an empty nodeset, the general thing to do I think is something like /parent::node(), which will be empty because the root has no parents.

I suppose you could do something like /root/list/item[position() = (last() + 1)], but it would give you the same result as anything that returned no nodes. So I'm not quite sure what you're actually trying to accomplish.

Peter Cooper Jr.
I'm using the xPath as a write address rather than a read address. See update above.
Rory Becker