Here are three XML-trees
(1)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1">
<section id="2"/>
<section id="3"/>
<section id="9"/>
</section>
<section id="4">
<section id="5">
<section>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</section>
</section>
</content>
(2)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1"/>
<section id="2">
<section id="9">
<section id="10">
<section id="11"/>
</section>
</section>
<section>
<section id="4">
<section id="5"/>
</section>
</section>
<section/>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</content>
The desired result is in both cases the id 5.
With XSLT 1.0 and XPath 1.0 I can either get the ancestor from (1)
<xsl:value-of select="//bookmark/ancestor::*[@id][1]/@id"/>
or the preceding node from (2)
<xsl:value-of select="//bookmark/preceding::*[@id][1]/@id"/>
How do I get the nearest ancestor or preceding node with an id from my bookmark?
I need a single xsl:value-of which matches both cases. Thanks.
EDIT:
The solution should also cover this structure. Desired id is still 5.
(3)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1">
<section id="2"/>
<section id="3"/>
<section id="9"/>
</section>
<section id="4">
<section>
<section id="10"/>
<section id="5"/>
<section>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</section>
</section>
</content>
Try with :
It returns
5
for both XML documents.EDIT:
In such conditions you could use simple
xsl:choose
:Another general solution:
Use:
Verification: Using XSLT as host of XPath, the following transformation:
when applied on any of the provided three XML documents, produces the wanted, correct result:
5
I strongly recomment using the XPath Visualizer for playing with / learning XPath.