Reputation: 23
I have searched, but might have missed something obvious just because I don't know what to search for. And I found it hard to explain my question as a simple question, so let me explain: I am using the following code (XSLT 1.0 & XPath) to check if the parent to this node belongs to the last grand-parent node or not:
<xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">
It works exactly like I want. What I would like though is to make it more general in one way or the other, to make it work with even more parent nodes. I can add another template match and add another test:
<xsl:when test ="count(parent::*/parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">
Is there a way to add "parent::*/" in a recursive template loop instead of creating a lot of specific template matches? Or should I work out a better XPath code altogether?
Please note: I want to do a check for every level of parent nodes. Is the parent the last of the parents, is the grand-parent the last of the grand-parents, etc.
For clarity's sake, I use it like this:
<xsl:choose>
<xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">
<!-- show image A -->
</xsl:when>
<xsl:otherwise>
<!-- show image B -->
</xsl:otherwise>
</xsl:choose>
Upvotes: 2
Views: 2435
Reputation: 338118
<xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">
can be simplified to:
<xsl:when test="not(../following-sibling::*)">
In plain English "my parent does not have a following element sibling".
That would be easily modifiable to:
<xsl:when test="not(../../following-sibling::*)">
In plain English "my parent's parent does not have a following element sibling". Etc.
To check all ancestors at the same time:
<xsl:when test="not(ancestor::*/following-sibling::*)">
In plain English "none of my ancestors has a following element sibling".
To check parent and grandparent at the same time:
<xsl:when test="not(ancestor::*[position() <= 2]/following-sibling::*)">
In plain English "none of my two closest ancestors has a following element sibling".
EDIT To check all ancestors individually, either use a recursive template (advantage: the position of the inner <xsl:apply-templates>
determines if you effectively go up or down the list of ancestors):
<xsl:template match="*" mode="line-img">
<xsl:if test="following-sibling::*">
<!-- show image A -->
</xsl:if>
<xsl:if test="not(following-sibling::*)">
<!-- show image B -->
</xsl:if>
<xsl:apply-templates select=".." mode="line-img" />
</xsl:template>
<!-- and later... -->
<xsl:apply-templates select=".." mode="line-img" />
...or a simple for-each loop (always works in document order):
<xsl:for-each select="ancestor::*">
<xsl:if test="following-sibling::*">
<!-- show image A -->
</xsl:if>
<xsl:if test="not(following-sibling::*)">
<!-- show image B -->
</xsl:if>
</xsl:for-each>
...or, to be completely idiomatic (always works in document order):
<xsl:template match="*" mode="line-img">
<xsl:if test="following-sibling::*">
<!-- show image A -->
</xsl:if>
<xsl:if test="not(following-sibling::*)">
<!-- show image B -->
</xsl:if>
</xsl:template>
<!-- and later... -->
<xsl:apply-templates select="ancestor::*" mode="line-img" />
Upvotes: 4