xpath - preceding - xslt following sibling

XPath:select all following siblings until another sibling (2)

Simpler than the accepted answer:

  • Find a node anywhere whose id is '1'
  • Now find all the following sibling node elements
  • ...but only if those elements also have a node with id="2" somewhere after them.

Shown in action with a more clear test document (and legal id values):

xml = '<root>
<node id="a"/><node id="b"/>
<node id="c">content</node>
<node id="d"/><node id="e"/><node id="f"/>
<node id="g">content</node>
<node id="h"/><node id="i"/>

# A Ruby library that uses libxml2; http://nokogiri.org
require 'nokogiri'; doc = Nokogiri::XML(xml)

expression = "//node[@id='c']/following-sibling::node[following::node[@id='g']]"
puts doc.xpath(expression)
#=> <node id="d"/>
#=> <node id="e"/>
#=> <node id="f"/>

Here is an excerpt of my xml :

<node id="1">content</node>
<node id="2">content</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 ?

XPath 2.0 has the operators '<<' and '>>' where node1 << node2 is true if node1 precedes node2 in document order. So based on that with XPath 2.0 in an XSLT 2.0 stylesheet where the current node is the node[@id = '1'] you could use

  following-sibling::node[not(text()) and . << current()/following-sibling::node[@od][1]]

That also needs the current() function from XSLT, so that is why I said "with XPath 2.0 in an XSLT 2.0 stylesheet". The syntax above is pure XPath, in an XSLT stylesheet you would need to escape '<<' as '&lt;&lt;'.