[xsl] Subject: Counting Path Occurrences

Subject: [xsl] Subject: Counting Path Occurrences
From: "Scott Coon" <scoon@xxxxxxxxxxxxx>
Date: Thu, 29 Mar 2007 18:35:54 -0700
Hi - I'm trying to write a generic stylesheet to count occurrences of
full paths to elements.  For example, I'd like input like this:

<a>
	<b>
		<x>
			<w>blah</w>
		</x>
		<y>bleh</y>
	</b>
	<b>
		<x>
			<w>blih</w>
		</x>
		<x>
			<w>bloh</w>
		</x>
	</b>
	<c>
		<w>blwh</w>
		<w>blyh</w>
	</c>
</a>

To generate this output:

/a - 1
/a/b - 2
/a/b/x - 3
/a/b/x/w - 3
/a/b/y - 1
/a/c - 1
/a/c/w - 2

So, start with a stylesheet function to generate the paths (/a/b/x)
using the ancestor-or-self axis:

<xsl:function name="gn:path">
	<xsl:param name="node" as="node()"/>
	<xsl:for-each select="$node">
		<xsl:for-each select="ancestor-or-self::*"><xsl:value-of
select="concat('/', name())"/></xsl:for-each>
	</xsl:for-each>
</xsl:function>

My hope was to use it like this in the template that matches "/":

<xsl:for-each-group select="descendant-or-self::*"
group-by="gn:path(.)">
	Path: <xsl:value-of select="gn:path(.)"/> - Count: <xsl:value-of
select="count(current-group())"/>
</xsl:for-each-group>

Unfortunately, stylesheet functions only return item()*, not string, so
this doesn't work - the current-grouping-key() is always something like
"/a" or "/x".  Could I concatenate all the pieces of the sequence with a
template, then return that out of function (since a 1-element sequence
is the same as the single element?)  Or is there a cleaner way?

Thanks,
Scott C.

Current Thread