Subject: [xsl] XSLT 1.0 Muenchian Grouping From: "Steve Sze" <steveyksze@xxxxxxxxx> Date: Sat, 15 Jul 2006 17:01:45 -0400 |
Yes, forgot to point out that Im using XSLT 1.0. Mukul, based on the Muenchian method, your code works well. The explanation below is super! Based on everyone's explanation, I did approach this problem with the wrong method. I approach this problem with my Java experience. I guess Ive rely too much on Vectors & Arrays.
Thank You All!!!! Steve
Hi Steve, As Mike pointed out, this problem is best solved using Muenchian grouping method, if you are using XSLT 1.0.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/report"> <html> <head> <title/> </head> <body> <table border="1"> <xsl:for-each select="//entry[generate-id() = generate-id(key('by-country', country)[1])]"> <tr> <td><xsl:value-of select="country" /></td> </tr> <tr> <td>Group</td> <td>Name</td> <td>id</td> </tr> <xsl:for-each select="key('by-country', country)"> <tr> <td><xsl:value-of select="../@type" /></td> <td><xsl:value-of select="name" /></td> <td><xsl:value-of select="id" /></td> </tr> </xsl:for-each> </xsl:for-each> </table> </body> </html> </xsl:template>
Regards, Mukul
This is a classic grouping problem which is best tackled using xsl:for-each-group in XSLT 2.0, or Muenchian grouping (see http://www.jenitennison.com/xslt/grouping) in 1.0. The 2.0 solution is:
<xsl:for-each-group select="//entry" group-adjacent="country"> <h2><xsl:value-of select="current-grouping-key()"/></h2> <table> <thead>...</thead> <tbody> <xsl:for-each select="current-group()"> <tr> <td><xsl:value-of select="../@type"/></td> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="id"/></td>
Michael Kay http://www.saxonica.com/
Others have given solutions but let me just observe (given a recent thread about mutable variables) that the solutions follow the natural human language description rather than a solution that you'd program in an imperative programming language.
If you were describing the problem to a person you'd say that you want to group the items by country and put a country heading at the top of each group.
You wouldn't (or at least I wouldn't) introduce the notion of state and some temporary variable holding the last seen country and say that for each item you need to compare the current country with the value of the variable stored at the last item.
The human-oriented description does not introduce any variables at all, and the XSLT solutions typically don't use any variables either. This is almost always the case when someone more familiar with imperative programming languages has problems with the fact that xsl variables "don't change". Usually it's not that you don't need to change the value of a variable, it's that you don't need a variable at all.
Right. And explaining how to do that, you wouldn't say "pick up the items one at a time and if you've already done one with that country, skip it", you'd say "pick up one from each country and with it...", and if someone asked "okay which one" you'd say "it doesn't matter but if you really need me to say, the first one will do".
Thus the declarative approach also allows the implementor to optimize where convenient, rather than fussing over details that don't really matter to the solution.
Cheers, Wendell
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] textarea xml/html ptoblem, Wendell Piez | Thread | [xsl] Generate instance document fr, v.omprakash |
Re: [xsl] Re: Keeping a running tot, Dimitre Novatchev | Date | [xsl] Generate instance document fr, v.omprakash |
Month |