Reputation: 23062
if I have a Nokogiri::XML::Element, how do I figure its child index in relation to its parent? That is:
<foo> <-- parent
<bar/> <-- 1st child
<bar/> <-- 2nd child
</foo>
In Javascriptland, jQuery has index(), but Nokogiri doesn't. Nokogiri does provide a path method, but that returns an XPath string like "/foo/bar[2]"
and truncates bar[1]
to bar
to boot, so turning that back into a number is a little hairy:
element.path.split('/').last.slice(/[0-9]+/) || '1' # quick'n'dirty
element.path.split('/').last.slice(/\[([0-9]+)\]/, 1) || '1' # a bit safer
Upvotes: 3
Views: 2376
Reputation: 303244
Technique 1: Find my siblings, see where I fit within them:
idx = element.parent.element_children.index(element)
# Alternatively:
idx = element.parent.xpath('*').index(element)
Technique 2: Count the number of element (not text) nodes before me:
idx = element.xpath('count(preceding-sibling::*)').to_i
# Alternatively, if you want to waste time and memory:
# idx = element.xpath('preceding-sibling::*').length
Technique 2 is measurably faster.
Upvotes: 3
Reputation: 754
This selects nodes of the same element name and returns the index:
element.parent.xpath(element.name).index(element)
Upvotes: 1
Reputation: 54984
How about:
element.parent.children.index(element)
To consider only non-text nodes:
element.xpath('../*').index(element)
To consider only bar nodes:
element.xpath('../bar').index(element)
Upvotes: 7