[xsl] Avoiding treating duplicate items when grouping

Subject: [xsl] Avoiding treating duplicate items when grouping
From: Aitor San Juan <asanjuan@xxxxxxxxxxxxxx>
Date: Wed, 1 Oct 2003 10:04:53 +0200
Hello all!

	I have one question and I think I'm stuck. Here you are a sample
input XML document.
Neither the <rec> elements nor the <user> elements within the <rec> elements
are ordered in
any particular order.

	<users>
		<rec date="2001-01-24">
			<user gid="G2" last-access="2001-01-24
17:50:37.72677">M-1</user>
			<user gid="G1" last-access="2001-01-24
18:05:12.816369">F-1</user>
			<user gid="G2" last-access="2001-01-24
18:10:12.302868">M-4</user>
			<user gid="G1" last-access="2001-01-24
18:10:12.846846">F-2</user>
			<user gid="G2" last-access="2001-01-24
18:10:13.367885">M-5</user>
			<user gid="G2" last-access="2001-01-24
18:05:14.113309">M-3</user>
		</rec>
		<rec date="2001-01-25">
			<user gid="G2" last-access="2001-01-25
11:42:36.842908">M-2</user>
			<user gid="G2" last-access="2001-01-25
11:43:05.695899">M-4</user>
		</rec>
		<rec date="2001-10-11">
			<user gid="G1" last-access="2001-10-11
11:03:39.7898">F-1</user>
			<user gid="G1" last-access="2001-10-11
09:50:47.711776">F-2</user>
		</rec>
		<rec date="2001-12-31">
			<user gid="G1" last-access="2001-12-31
11:38:49.700800">M-2</user>
			<user gid="G1" last-access="2001-12-31
19:14:09.822549">M-1</user>
		</rec>
		...
	</users>


	Given a year and month, what I want is to obtain a list (in HTML) of
those users
(ordered by user name: M-1, M-2, etc.) whose last access was in that month
of the year
grouped by "gid". Applying the Muenchian method for grouping, I have written
the following
style sheet. For example, fiven the year "2001" and month January (01), the
style sheet
works but the user M-4 is included twice because it appears in record of
2001-01-24 and in
record of 2001-01-25. So how can I avoid duplicates?, that is, each user
satisfying the
year and month given, should appear only once in the list. If a user appears
in several
records, I like to select that with the most recent last access. A user will
not appear
more than once within a record.

	Any help would be highly appreciated. Thanks in advance.


My XSL file:
============

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">

	
<!--================================================================-->
	<!-- Parameter of the form: yyyy-mm
-->
	
<!--================================================================-->
	<xsl:param name="theDate"/>

	
<!--================================================================-->
	<!-- Output format
-->
	
<!--================================================================-->

	<xsl:output method="html" indent="yes" omit-xml-declaration="yes"
		doctype-public="-//W3C//DTD HTML 4.0 Transitional//EN"
		encoding="ISO-8859-1"/>


	<xsl:strip-space elements="*"/>

	
<!--================================================================-->
	<!-- Grouping criteria (Muenchian method)
-->
	
<!--================================================================-->
	<xsl:key name="group-by-gid"
match="rec[substring(@date,1,7)=$theDate]/user" use="@gid"/>


	<xsl:template match="users">
		<html>
		<head>
		<title>User Stats</title>
		</head>
		<body>
		<!--
			 Check whether there are datat or not
		-->
		<xsl:choose>
			<xsl:when
test="count(./rec[substring(@date,1,7)=$theDate]) > 0">
				<div align="center">
				<table border="1" cellpadding="5"
cellspacing="0">
  				<tbody>
					<xsl:for-each
select="./rec/user[count(.|key('group-by-gid',@gid)[1])=1]">
						<xsl:sort select="@gid"
data-type="number" order="ascending"/>
						<!-- Writes a table header
with the value of the grouping criteria -->
						<tr>
							<th colspan="2"
align="center"><xsl:value-of select="@gid"/></th>
						</tr>
						<tr>
							<td
align="center">User</td>
							<td
align="center">Last Access</td>
						</tr>
						<xsl:for-each
select="key('group-by-gid',@gid)">
							<!-- Alphabetical
order by user name -->
							<xsl:sort select="."
data-type="text" order="ascending"/>
							<xsl:apply-templates
select="."/>
						</xsl:for-each>
					</xsl:for-each>
				</tbody>
				</table></div>
			</xsl:when>
			<xsl:otherwise>
				<div align="center">
				<table border="0" cellspacing="0"
cellpadding="0" style="margin-left:.5cm">
					<tbody>
						<tr>
							<td width="370"
align="center" valign="middle">NO USERS</td>
						</tr>
					</tbody>
				</table>
				</div>
			</xsl:otherwise>
		</xsl:choose>
		</body>
		</html>
	</xsl:template>


	<xsl:template match="user">
		<tr>
			<td align="left"><div style="font-family:monospace">
				<xsl:value-of select="."/>
			</td>

			<td align="center">
				<xsl:value-of select="@last-access"/>
			</td>
		</tr>
	</xsl:template>

</xsl:stylesheet>


************ LEGEZKO OHARRA / AVISO LEGAL / LEGAL ADVICE *************
Mezu honek isilpeko informazioa gorde dezake, edo jabea duena, edota legez
babestuta dagoena.
Zuri zuzendua ez bada, bidali duenari esan eta ezabatu, inori berbidali
edo gorde gabe,legeak debekatzen duelako mezuak erabiltzea baimenik gabe.
--------------------------------------------------------------------------
Este mensaje puede contener información confidencial, en propiedad o
legalmente protegida.
Si usted no es el destinatario, le rogamos lo comunique al remitente
y proceda a borrarlo, sin reenviarlo ni conservarlo, ya que su uso no 
autorizado está prohibido legalmente.
--------------------------------------------------------------------------
This message may contain confidential, proprietary or legally privileged
information.
If you are not the intended recipient of this message, please notify it to
the sender and delete without resending or backing it, as it is legally
prohibited.
************************************************************************** 



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread