Re: [xsl] Grouping problem

Subject: Re: [xsl] Grouping problem
From: Andrew Franz <afranz0@xxxxxxxxxxxxxxxx>
Date: Tue, 02 Aug 2005 07:11:08 +1000
Mukul Gandhi wrote:

Thanks Mike for the XSLT 2.0 way to solve the problem. But it was
surprising for me that the problem cannot be solved in XSLT 1.0 using
preceding-sibling axis.

Regards,
Mukul



Solution #1: <xsl:template match="groups"> <xsl:for-each select="group"> <xsl:sort select="@name" /> <xsl:if test="not(@name = preceding-sibling::group/@name)"> <group name="{@name}" /> </xsl:if> </xsl:for-each> </xsl:template>

Solution #2:
<xsl:template match="groups">
   <xsl:for-each select="group">
   <xsl:sort select="@name" />
       <xsl:apply-templates select="." />
   </xsl:for-each>
</xsl:template>

<xsl:template match="group[(@name = preceding-sibling::group/@name)]" priority="+1" />
<xsl:template match="group">
<group name="{@name}" />
</xsl:template>


Solution #3:
<xsl:key name="k2" match="group" use="@name" />

<xsl:template match="groups">
   <xsl:for-each select="group">
   <xsl:sort select="@name" />
       <xsl:apply-templates select="." />
   </xsl:for-each>
</xsl:template>

<xsl:template match="group" priority="-1" />
<xsl:template match="group[generate-id() = generate-id(key('k2', @name)[1])]">
group[<xsl:value-of select="@id" />]=<xsl:value-of select="@name" /><br/>
</xsl:template>




On 8/1/05, Michael Kay <mike@xxxxxxxxxxxx> wrote:


When comparing two node-sets,

X = Y

means "some $x in X equals some $y in Y"

But when you do

name(X) = name(Y)

you are comparing two strings, not two node-sets. If X is a node-set, then
name(X) is the name of the first node in X, and name(Y) is the name of the
first node in Y. (In XSLT 2.0, with version="2.0", you would get an error
trying to apply name() to a node-set containing more than one node. The
change has been made to catch this common mistake.)

In 2.0 you can write

select="*[not(name() = preceding-sibling::*/name())]"

but of course it would be more efficient to use xsl:for-each-group.

Michael Kay
http://www.saxonica.com/




-----Original Message-----
From: Mukul Gandhi [mailto:gandhi.mukul@xxxxxxxxx]
Sent: 01 August 2005 07:57
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] Grouping problem

I have the following XML file -
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <a>1</a>
  <b>2</b>
  <d>3</d>
  <d>4</d>
  <b>5</b>
  <b>6</b>
  <c>7</c>
  <c>8</c>
  <a>9</a>
</root>

I am trying to do grouping operation with the following XSL -
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

     <xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>

     <xsl:template match="/root">
        <groups>
          <xsl:for-each select="*[not(name() =
name(preceding-sibling::*))]">
           <group name="{name()}" />
          </xsl:for-each>
        </groups>
     </xsl:template>

</xsl:stylesheet>

I am expecting output -
<groups>
  <group name="a" />
  <group name="b" />
  <group name="c" />
  <group name="d" />
</groups>

But I get output -
<?xml version="1.0" encoding="UTF-8"?>
<groups>
<group name="a"/>
<group name="b"/>
<group name="d"/>
<group name="d"/>
<group name="b"/>
<group name="b"/>
<group name="c"/>
<group name="c"/>
</groups>

Where is the problem?

This is tested with Xalan-J 2.6.0 and Saxon 8.4

Regards,
Mukul

Current Thread