RE: [xsl] Grouping and Key Problem

Subject: RE: [xsl] Grouping and Key Problem
From: "M. David Peterson" <m.david@xxxxxxxxxx>
Date: Fri, 9 Apr 2004 16:16:42 -0600
generate-id() coupled with key() is only going to give you the first
instance of each distinct element in a group.  With that information you
can then test each of the elements against this information and group
them as such.  I wish I had the time to look through your particular
code a bit more and figure out your specific error.  But I do have the
time to copy and paste a quick and simple example that highlights the
correct process using apply-templates and a passed parameter containing
all of the ungrouped elements that can then be used to test against each
distinct group.  Let me know if you have any further questions and if I
don't have the time to help I am confident you will find several other
list members who will be more than happy to help out.

Best of luck!

<M:D/>

Sample XML:

<?xml version="1.0"?>
<crayons>
  <crayon color="blue" brand="crayola"/>
  <crayon color="yellow" brand="generic"/>
  <crayon color="violet" brand="generic"/>
  <crayon color="violet" brand="crayola"/>
  <crayon color="fuscia" brand="crayola"/>
  <crayon color="red" brand="generic"/>
  <crayon color="red" brand="crayola"/>
  <crayon color="blue" brand="generic"/>
  <crayon color="green" brand="generic"/>
  <crayon color="green" brand="crayola"/>
  <crayon color="yellow" brand="crayola"/>
  <crayon color="orange" brand="generic"/>
  <crayon color="orange" brand="crayola"/>
  <crayon color="fuscia" brand="generic"/>
</crayons>

Sample XSLT:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
<xsl:key name="brand" match="@brand" use="."/>
<xsl:template match="crayons">
  <xsl:apply-templates select="crayon[generate-id(@brand) =
generate-id(key('brand', @brand))]" mode="brand">
    <xsl:with-param name="crayons" select="crayon"/>
  </xsl:apply-templates>
</xsl:template>
<xsl:template match="crayon" mode="brand">
<xsl:param name="crayons"/>
<xsl:variable name="brand" select="@brand"/>
  Brand: <xsl:value-of select="@brand"/><br/>
  <xsl:apply-templates select="$crayons[@brand = $brand]" mode="sort"/>
</xsl:template>
<xsl:template match="crayon" mode="sort">
  Color: <xsl:value-of select="@color"/><br/>
</xsl:template>
</xsl:stylesheet>

Sample output:

  Brand: crayola<br/>
  Color: blue<br/>
  Color: violet<br/>
  Color: fuscia<br/>
  Color: red<br/>
  Color: green<br/>
  Color: yellow<br/>
  Color: orange<br/>
  Brand: generic<br/>
  Color: yellow<br/>
  Color: violet<br/>
  Color: red<br/>
  Color: blue<br/>
  Color: green<br/>
  Color: orange<br/>
  Color: fuscia<br/>

-----Original Message-----
From: James Hunt [mailto:jamesanthonyhunt@xxxxxxxxx] 
Sent: Friday, April 09, 2004 2:37 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Grouping and Key Problem

Hi Mukul,

Thanks for all your help, but I'm only getting the
first customer from each date. 

Current Output:

12/13/2001 
 John  Water Plant 4 
       Mail        5 
12/14/2001 
 Jimmy Mail        5 

What I need:
12/13/2001 
 John Water Plant 4 
 Mail             5 
 Jimmy      Mail  5 
12/14/2001 
 Jimmy      Mail  5 

Can you tell me what I need to do?

Thanks,
James

--- Mukul Gandhi <mukulgandhi2003@xxxxxxxxxxx> wrote:
> Hi James,
>   I have written the logic specific to your
> requirement. Hope its useful.
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> <xsl:output method="html" version="1.0"
> encoding="UTF-8" indent="yes"/>
> <xsl:key name="kDate" match="Table" use="date"/>
> <xsl:key name="kCustomer" match="Table"
> use="concat(date,'+',CustomerName)"/>
> 
> <xsl:template match="/NewDataSet">
>   <html>
>     <table border="1">
>       <xsl:for-each select="Table">
> 	<xsl:if test="generate-id(.) =
> generate-id(key('kDate', date)[1])">
> 	<tr>
> 	  <td colspan="4">
> 	    <xsl:value-of select="date"/>
> 	  </td>
> 	</tr>
> 	<xsl:for-each select="key('kDate', date)">
> 	   <xsl:if test="generate-id(.) =
>
generate-id(key('kCustomer',concat(date,'+',CustomerName))[1])">
> 	     <xsl:if test="position() = 1">
> 		<tr>
> 		  <td/>
> 		  <td>
> 		   <xsl:value-of select="CustomerName"/>
> 		  </td>
> 		  <td>
> 		    <xsl:value-of select="ServiceName"/>
> 		  </td>
> 		  <td>
> 		    <xsl:value-of select="TimesPerDay"/>
> 		  </td>
> 	      </tr>
> 	 </xsl:if>
> 								 <xsl:if
test="not(position() = 1)">
> 	   <tr>
> 	     <td colspan="2"/>
> 		<td>
> 		  <xsl:value-of select="ServiceName"/>
> 		</td>
> 		<td>
> 		  <xsl:value-of select="TimesPerDay"/>
> 		</td>
> 	   </tr>
> 	 </xsl:if>
>    </xsl:if>
> </xsl:for-each>
> </xsl:if>
> </xsl:for-each>
> 
> </table>
> </html>
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> Regards,
> Mukul
> 
>  --- James Hunt <jamesanthonyhunt@xxxxxxxxx> wrote:
> >
> I'm having problems with grouping and the use of
> > keys
> > can anyone tell me what I'm doing wrong here. I
> have
> > two records of John on the 12/13/2001 They
> shouldn't
> > display separated. How can I make this tranform
> into
> > something like this:
> > 
> > 12/13/2001
> > John
> >   Water Plant
> >   Mail
> > 12/13/2001
> > Jimmy
> >   Mail
> > 
> > Right now it is giving this:
> > 
> > 12/13/2001
> > John
> >   Water Plant
> >   Mail
> > John
> >   Water Plant
> >   Mail
> > 12/13/2001
> > Jimmy
> >   Mail
> > 
> > XML File
> > 
> > <?xml version="1.0" encoding="UTF-8"?>
> > <NewDataSet>
> > 	<Table>
> > 		<mymonth>12</mymonth>
> > 		<myday>13</myday>
> > 		<myyear>2001</myyear>
> > 		<CustomerName>John</CustomerName>
> > 		<date>12/13/2001</date>
> > 		<TimesPerDay>4</TimesPerDay>
> > 		<ServiceName>Water Plant</ServiceName>
> > 	</Table>
> > 	<Table>
> > 		<mymonth>12</mymonth>
> > 		<myday>13</myday>
> > 		<myyear>2001</myyear>
> > 		<CustomerName>John</CustomerName>
> > 		<date>12/13/2001</date>
> > 		<TimesPerDay>5</TimesPerDay>
> > 		<ServiceName>Mail</ServiceName>
> > 	</Table>
> > 	<Table>
> > 		<mymonth>12</mymonth>
> > 		<myday>13</myday>
> > 		<myyear>2001</myyear>
> > 		<CustomerName>Jimmy</CustomerName>
> > 		<date>12/13/2001</date>
> > 		<TimesPerDay>5</TimesPerDay>
> > 		<ServiceName>Mail</ServiceName>
> > 	</Table>
> > 	<Table>
> > 		<mymonth>12</mymonth>
> > 		<myday>14</myday>
> > 		<myyear>2001</myyear>
> > 		<CustomerName>Jimmy</CustomerName>
> > 		<date>12/14/2001</date>
> > 		<TimesPerDay>5</TimesPerDay>
> > 		<ServiceName>Mail</ServiceName>
> > 	</Table>
> > </NewDataSet>
> > 
> > 
> > 
> > 
> > XSLT
> > 
> > 
> > 
> > <?xml version="1.0" encoding="UTF-8"?>
> > 
> > <xsl:stylesheet version="1.0"
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> > 	<xsl:output method="html" version="1.0"
> > indent="yes"/>
> > 	<xsl:key name="kCustomer" match="Table"
> > use="CustomerName"/>
> > 	<xsl:key name="kDate" match="Table" use="date"/>
> > 
> > 	<xsl:template match="NewDataSet">
> > 		<head>
> > 			<title>Employee's Week Schedule</title>
> > 			<link href="../css/reports.css" type="text/css"
> > rel="stylesheet" />
> > 		</head>	
> > 
> > 		<table border="0" cellpadding="4"
> > style="border-collapse:collapse;" width="100%">
> > 			<tr>
> > 				<td colspan="1">
> > 					<b>Customer Name</b>
> > 				</td>
> > 				<td colspan="1">
> > 					<b>Service Name</b>
> > 				</td>	
> > 				<td colspan="2">
> > 					<b>Times Per Day</b>
> > 				</td>

> > 			</tr>					
> > 				<xsl:apply-templates
> select="Table[generate-id()
> > =
> > generate-id(key('kDate', date))]" mode="row1"/>			
> 	
> > 
> > 		</table >
> > 	</xsl:template>	
> > 
> > 
> > 	<xsl:template match="Table" mode="row1">	
> > 		<tr>
> > 			<td colspan="4">		
> > 				<div
> style="background-color:red"><xsl:value-of
> > select="date"/></div>
> > 				<xsl:apply-templates
> > select="parent::NewDataSet/Table[date =
> > current()/date][CustomerName = key('kCustomer',
> > CustomerName)/CustomerName]" mode="row2"/>
> > 			</td>
> > 		</tr>
> > 
> > 	</xsl:template>
> > 
> > 	<xsl:template match="Table" mode="row2">
> > 		<tr>
> > 			<td colspan="4">			
> > 				<hr/>
> > 				<xsl:value-of select="CustomerName"/>
> >   			      <xsl:apply-templates
> > select="parent::NewDataSet/Table[date =
> > current()/date][CustomerName =
> > current()/CustomerName][ServiceName]"
> mode="row3"/>
> > 			</td>			
> > 		</tr>
> > 	</xsl:template>
> > 	
> > 	<xsl:template match="Table" mode="row3">
> > 		<tr>
> > 			<td />
> > 			<td colspan="1">			
> > 				<xsl:value-of select="ServiceName"/>
> > 			</td>
> > 			<td colspan="2">			
> > 				<xsl:value-of select="TimesPerDay"/>
> > 			</td>						
> > 		</tr>		
> > 	</xsl:template>
> > 	
> > </xsl:stylesheet>
> > 
> > 
> > =====
> > Home: (513) 661 - 8007 
> > Cell: (513) 884 - 4868 
> > Email: jamesanthonyhunt@xxxxxxxxx
> > 
> > __________________________________
> > Do you Yahoo!?
> > Yahoo! Small Business $15K Web Design Giveaway 
> > http://promotions.yahoo.com/design_giveaway/
> >  
> 
>
________________________________________________________________________
> Yahoo! India Matrimony: Find your partner online.
> http://yahoo.shaadi.com/india-matrimony/
> 


=====
Home: (513) 661 - 8007 
Cell: (513) 884 - 4868 
Email: jamesanthonyhunt@xxxxxxxxx

__________________________________
Do you Yahoo!?
Yahoo! Small Business $15K Web Design Giveaway 
http://promotions.yahoo.com/design_giveaway/

Current Thread