I am using Nokogiri.
Suppose I have a deeply nested path:
//h1/h2/h3/h4/h5
I think I can use the following path:
//h1/*/*/*/h5
Is there any way I can avoid using multiple asterisks? Something like //h1/.../h5
?
I don't want to keep counting the levels of nesting.
If you want to select all h5
that are exactly 4 levels below their h1 ancestor, use:
//h5[ancestor::*[4][self::h1]]
XSLT - based verification:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="//h5[ancestor::*[4][self::h1]]"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<head/>
<body>
<h1>First Main title
<a>
<b>
<c>
<h5 id="id1"/>
<d>
<h5 id="id2"/>
</d>
</c>
</b>
</a>
</h1>
</body>
</t>
the XPath expression is evaluated and the result of the evaluation (the selected h1
elements (in this case just one)) is copied to the output:
<h5 id="id1"/>
If you don't want to count the number of the intermediate levels, butare sure that they don't exceed a certain number (say 7), you can write:
//h1[descendent::*[not(position() > 7)][self::h1]]
This selects any h5
descendent of any h1
, where the "distance" in levels between the h1
and the descendent h5
doesn't exceed 7.
Do note:
An expression like the below -- as suggested in other answers:
//h1//h5
incorrectly selects for the above document:
<h5 id="id1"/>
<h5 id="id2"/>
The second of the two selected h5
elements is at a greater distance than the wanted one from its h1
ancestor.
for all h5 elements that descend from an h1 use:
//h1//h5
Or you might like the simpler css style:
h1 h5
Just use: //
, i.e.: //h5
. This XPath will select all h5
elements. See spec: http://www.w3.org/TR/xpath/#path-abbrev
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With