[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Only first rows (after the sort)


Subject: Re: [xsl] Only first rows (after the sort)
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 15 Aug 2006 10:51:44 -0400

Dennis,

As you say, this is a de-duplicating problem; I'd use keys to achieve it (an approach that has the virtue of scalability). In this case it has to be a "compound key" constituted of two values, namely the category and year of each example, but that's not too hard:

<xsl:key name="unique-examples" match="example" use="concat(category, year)"/>

Then iterate through your examples:

<xsl:apply-templates select="//example">
<xsl:sort select="category"/>
<xsl:sort select="year"/>
<!-- if your data is already sorted, or you don't care, you can skip this -->
</xsl:apply-templates/>


and for each one, test to see if it's the first one with its category-year combination:

<xsl:template match="example">
<xsl:if test="generate-id() =
generate-id(key('unique-examples',concat(category,year)))">
<!-- this idiom is called 'Muenchian grouping', after
Steve Muench, who first figured out how to use keys to de-duplicate -->


do your stuff here

  </xsl:if>
</xsl:template>

As you might guess by noticing that de-duplicating subsumes grouping, in XSLT 2.0 you can use grouping constructs to achieve the same thing much more nicely.

Cheers,
Wendell

At 10:22 AM 8/15/2006, you wrote:
Hi,

I have a problem transforming an XML file to the desired table
structure. I hope someone can help me.

Here is the XML file I use:
<example>
  <category>XML</category>
  <year>2005</year>
</example>
<example>
  <category>XSL</category>
  <year>2005</year>
</example>
<example>
  <category>XSL</category>
  <year>2006</year>
</example>
<example>
  <category>XML</category>
  <year>2005</year>
</example>
...

Here is how the table should look eventually:
Catagory    Year
XML         2005
XSL         2005
XSL         2006
...

My current XSL:

<xsl:for-each select="example">
<xsl:sort select="category"><xsl:sort select="year">
<tr><td><xsl:value-of select="./category"></td><td><xsl:value-of
select="./year"></td></tr>
</xsl:for-each>

This results in:
Catagory    Year
XML         2005
XML         2005
XSL         2005
XSL         2006
...

So what I'm trying to do is to skip rows when the combination of
category and year are identical  (skip the duplicates). I've tried to
put it in an <xsl:if> combined with <xsl:variable> construction, but I
just can't get it right. Does anyone have an idea?

Kind regards,
Dennis


Current Thread
Keywords