In my attempt to answer question XSLT - Tricky Transformation I came across the following task:
For each tag
<MMM>
count the number of leaf nodes in the second<MMM>
child tag.
Define "leaf node" as an <MMM>
tag that does not have other <MMM>
tags as children. It may have other tags as children, though.
I ended up with two expressions:
<xsl:variable name="just_children" select="count(MMM[position() = 2 and count(MMM) = 0])"/>
<xsl:variable name="grandchildren_and_below" select="count(MMM[2]//MMM[count(MMM) = 0])"/>
The first one counts the leafs in the second child, the second one in all ancestors of the second child. I was not able to combine these two into one expression (except for the obvious summing which I have to do :-) ). Somehow I cannot make the node array index selector [2]
, the additional condition count(MMM) = 0
, and the ancestor path `//' fit into the same expression.
So, is there more a concise (and probably more elegant) way to write this expression?
Thanks a lot!
For testing you can use this input file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<MMM>
<MMM>
<MMM>
<MMM/>
<MMM/>
</MMM>
<MMM>
<MMM/>
<MMM>
<MMM/>
</MMM>
</MMM>
</MMM>
<MMM>
<MMM/>
</MMM>
</MMM>
and the following XSLT sheet:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="MMM">
<xsl:variable name="just_children" select="count(MMM[position() = 2 and count(MMM) = 0])"/>
<xsl:variable name="grandchildren_and_below" select="count(MMM[2]//MMM[count(MMM) = 0])"/>
<MMM just_children="{$just_children}" grandchildren_and_below="{$grandchildren_and_below}">
<xsl:apply-templates/>
</MMM>
</xsl:template>
</xsl:stylesheet>