Subject: Re: [xsl] 2 level Grouping through attributes From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 11 Feb 2002 19:09:42 +0000 |
Ronald Heller wrote: > Try the following: > <?xml version='1.0'?> > <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > <xsl:output method="xml" indent="yes"/> > <xsl:key name="level1" match="XML_OUTPUT/@UserID" use="." /> > > <xsl:key name="level2" match="XML_OUTPUT/@CategoryID" use="." /> > > <xsl:template match="/"> > <ROOT> > <xsl:for-each select="//XML_OUTPUT[generate-id(@UserID) = > generate-id(key('level1', @UserID)[1])]"> > <xsl:variable name="user"> > <xsl:value-of select="@UserID" /> > </xsl:variable> > > <xsl:comment> > <xsl:value-of select="generate-id(@UserID)" /> > </xsl:comment> > > <USER ID="{$user}"> > <xsl:for-each select="//XML_OUTPUT[generate-id(@CategoryID) > = generate-id(key('level2', @CategoryID)[1]) and @UserID=$user]"> > <xsl:variable name="category"> > <xsl:value-of select="@CategoryID" /> > </xsl:variable> > > <CATEGORY ID="{$category}" TITLE="{@CategoryTitle}"> > <xsl:for-each > select="//XML_OUTPUT[@CategoryID=$category and @UserID=$user]"> > <CONTENT_ITEM ID="{@ContentItemID}" > TITLE="{@ItemTitle}"> > </CONTENT_ITEM> > </xsl:for-each> > </CATEGORY> > </xsl:for-each> > </USER> > </xsl:for-each> > </ROOT> > </xsl:template> > </xsl:stylesheet> Unfortunately this runs into the classic trap with multi-level grouping using the Muenchian Method when identifying the unique values at the second level. See: > <xsl:for-each select="//XML_OUTPUT[generate-id(@CategoryID) > = generate-id(key('level2', @CategoryID)[1]) and @UserID=$user]"> Here, you go through all the XML_OUTPUT elements in the document, and then identify those that: (a) are the first in the document with that particular CategoryID; and (b) have the UserID equal to $user This will miss out XML_OUTPUT elements that have the same user ID, but *aren't* the first in the document with the particular category ID. So you won't pick up everything in the document. To do two-level grouping using the Muenchian method, the key for the second level has to incorporate information from the first level. I'd use the keys: <xsl:key name="level1" match="XML_OUTPUT" use="@UserID" /> <xsl:key name="level2" match="XML_OUTPUT" use="concat(@UserID, '+', @CategoryID)" /> This has two advantages: it gives you the right answer, and it means you can use the 'level2' key to find all the XML_OUTPUT elements with a particular user and category, which is a lot more efficient than searching through the entire document again. Then: <xsl:template match="/"> <ROOT> <xsl:for-each select="//XML_OUTPUT[generate-id() = generate-id(key('level1', @UserID)[1])]"> <xsl:variable name="user" select="@UserID" /> <xsl:comment> <xsl:value-of select="generate-id(@UserID)" /> </xsl:comment> <USER ID="{$user}"> <xsl:for-each select="key('level1', $user) [generate-id() = generate-id(key('level2', concat($user, '+', @CategoryID)[1])]"> <xsl:variable name="category" select="@CategoryID" /> <CATEGORY ID="{$category}" TITLE="{@CategoryTitle}"> <xsl:for-each select="key('level2', concat($user, '+', $category)"> <CONTENT_ITEM ID="{@ContentItemID}" TITLE="{@ItemTitle}"> </CONTENT_ITEM> </xsl:for-each> </CATEGORY> </xsl:for-each> </USER> </xsl:for-each> </ROOT> </xsl:template> --- The XSLT 2.0 solution is very similar: <xsl:template match="/"> <ROOT> <xsl:for-each-group select="//XML_OUTPUT" group-by="@UserID"> <xsl:variable name="user" select="@UserID" /> <xsl:comment> <xsl:value-of select="generate-id(@UserID)" /> </xsl:comment> <USER ID="{$user}"> <xsl:for-each-group select="current-group()" group-by="@CategoryID"> <xsl:variable name="category" select="@CategoryID" /> <CATEGORY ID="{$category}" TITLE="{@CategoryTitle}"> <xsl:for-each select="current-group()"> <CONTENT_ITEM ID="{@ContentItemID}" TITLE="{@ItemTitle}"> </CONTENT_ITEM> </xsl:for-each> </CATEGORY> </xsl:for-each> </USER> </xsl:for-each> </ROOT> </xsl:template> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] 2 level Grouping through , ronald heller | Thread | Re: [xsl] 2 level Grouping through , G. Ken Holman |
Re: [xsl] Displaying column headers, Dennis Daniels | Date | [xsl] newbie question: nested tags, Joe Cheng |
Month |