Reputation: 4054
I have been trying to write a XPath statement which will select the first preceding-sibling of a node. That sibling should have a particular node as its child.
For example:
<a>
<c></c>
....
<b></b>
</a>
<a></a>
....
....
<a></a>
<a>
<b> start </b>
</a>
In the above XML, if my context is at the node a
which has start
text inside its child b
. How can I select the preceding node a
whose child is b
?
I tried preceding-sibling::*[b][1]
but it only selects the node a
if b
is its first child. I also tried preceding-sibling::*[1][b]
but it only checks the first preceding a
node and if it doesn't contains b
, the test fails.
Note: I am using XSLT 1.0
Can anyone suggest me a solution?
Thnx in advance!!
Upvotes: 5
Views: 16754
Reputation: 338148
Like this. ("The first preceding sibling who has a <b>
child"):
preceding-sibling::a[b][1]
or this ("The first preceding sibling but only if it has a <b>
child"):
preceding-sibling::a[1][b]
Multiple predicates must be true one after another. Therefore, this:
preceding-sibling::a[b and position() = 1]
is equivalent to the second expression, but not to the first.
Upvotes: 7
Reputation: 116982
I believe that:
preceding-sibling::*[b][1]
or preferably:
preceding-sibling::a[b][1]
should work just fine.
I tried preceding-sibling::*[b][1] but it only selects the node a if b is its first child.
I don't think that is so.
Upvotes: 8
Reputation: 7173
With this input:
<root>
<a>
<c></c>
<b>SUCCESS</b>
</a>
<a>FAIL</a>
<a>FAIL</a>
<a>
<b> start </b>
</a>
</root>
and this stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a[b[.=' start ']]">
<xsl:copy>
<xsl:value-of select="preceding-sibling::a[b]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
it outputs
<root>
<a>
<c/>
<b>SUCCESS</b>
</a>
<a>FAIL</a>
<a>FAIL</a>
<a>SUCCESS</a>
</root>
Upvotes: 1