[xsl] Grouping, Counting, and Sorting

Subject: [xsl] Grouping, Counting, and Sorting
From: "Thomas F. O'Connell" <tfo@xxxxxxxxxxxxxx>
Date: Fri, 21 May 2004 11:58:32 -0500
I have some XML that looks like this:

<data>
	<node>
		<data>data</data>
		<valid>1</valid>
	</node>
	<node>
		<data>data</data>
	</node>
</data>

There can be any number and sequence of nodes. Some nodes are flagged
with a validity node.

I'm trying to transform it to HTML using XSL. Here are the conditions:

1. Group it by 100.
2. Sort it by whether or not the nodes have a "valid" node (descending
from valid to non-valid, which is just a binary existence check).
3. The output needs to be numbered sequentially.
4. The output needs to be formatted differently based on whether a
"valid" node is encountered.
5. The first chunk of the output needs to include a header.

Basically, I'm breaking it up into 100-row HTML tables.

Here's my current approach:

<table>
	<th>Header</th>
<xsl:apply-templates select="node[position() &lt;= 100]">
	<xsl:sort select="valid" />
</xsl:apply-templates>
</table>

<xsl:for-each select="node[position() mod 100=1 and position() &gt;
100]">
	<table cellpadding="0" cellspacing="0" border="0">
	<xsl:apply-templates
select=".|following-sibling::node[position()&lt;100]">
		<xsl:sort select="valid" />
	</xsl:apply-templates>
	</table>
</xsl:for-each>

<xsl:template match="node[valid=1]">
	<tr>
		<td class="valid">
			<xsl:variable name="number">
				<xsl:number value="count(preceding-sibling::*)+1" level="any"
format="1" />
			</xsl:variable>
			<xsl:value-of select="$number" />.
			<xsl:value-of select="data" />
		</td>
	</tr>
</xsl:template>

<xsl:template match="node[not(valid=1)]">
	<tr>
		<td class="invalid">
			<xsl:variable name="number">
				<xsl:number value="count(preceding-sibling::*)+1" level="any"
format="1" />
			</xsl:variable>
			<xsl:value-of select="$number" />.
			<xsl:value-of select="data" />
		</td>
	</tr>
</xsl:template>

Unfortunately, the result of this transformation neither sorts the
output, nor numbers the output sequentially. The grouping works, but I
was under the impression that the sort would apply to the nodes before
their positions were considered. What I understand less is why the sort
does not seem actually to order the nodes correctly in the output.

Any help is much appreciated.

Thanks!

-tfo

Current Thread