Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath : select all following siblings until another sibling

Tags:

xpath

Here is an excerpt of my xml :

<node/> <node/> <node id="1">content</node> <node/> <node/> <node/> <node id="2">content</node> <node/> <node/> 

I am positioned in the node[@id='1']. I need an Xpath to match all the <node/> elements until the next not empty node (here node[@id='2']).


Edit: the @id attributes are only to explain my problem more clearly, but are not in my original XML. I need a solution which does not use the @id attributes.


I do not want to match the empty siblings after node[@id='2'], so I can't use a naive following-sibling::node[text()=''].

How can I achieve this ?

like image 221
glmxndr Avatar asked Jan 29 '10 12:01

glmxndr


People also ask

How can XPath follow siblings?

We can use the concept of following-sibling in xpath for identifying elements in Selenium. It identifies the siblings of the context node. The siblings should be located at the equal level of the existing node and should have the same parent.

What is preceding-sibling and following-sibling in XPath?

XPath using Preceding-Sibling This is a concept very similar to Following-Siblings. The only difference in functionality is that of preceding. So, here, in contrast to Following-Sibling, you get all the nodes that are siblings or at the same level but are before your current node.

What is preceding and following XPath?

The following-sibling and preceding-sibling axes contain the siblings before or after the context node, and the following and preceding axes contain all nodes in the document before or after the context node, but: None of these axes contain attribute or namespace nodes.


1 Answers

You could do it this way:

 ../node[not(text()) and preceding-sibling::node[@id][1][@id='1']] 

where '1' is the id of the current node (generate the expression dynamically).

The expression says:

  • from the current context go to the parent
  • select those child nodes that
  • have no text and
  • from all "preceding sibling nodes that have an id" the first one must have an id of 1

If you are in XSLT you can select from the following-sibling axis because you can use the current() function:

<!-- the for-each is merely to switch the current node --> <xsl:for-each select="node[@id='1']">   <xsl:copy-of select="     following-sibling::node[       not(text()) and       generate-id(preceding-sibling::node[@id][1])       =       generate-id(current())     ]   " /> </xsl:for-each> 

or simpler (and more efficient) with a key:

<xsl:key    name="kNode"    match="node[not(text())]"    use="generate-id(preceding-sibling::node[@id][1])" />  <xsl:copy-of select="key('kNode', generate-id(node[@id='1']))" /> 
like image 98
Tomalak Avatar answered Nov 08 '22 12:11

Tomalak