xsl-list
[Top] [All Lists]

RE: [xsl] Grouping and Numbering

2007-05-28 22:54:30
Just to let you know what I did:
I first grouped the nodes based on the values of the group_id 
Notice the use of key and generate id combination( nothing new. It is one of
the classic grouping techniques) . 

Add the 
         <xsl:sort order="ascending" data-type="number"/>
After the first for loop ( I haven't done that in the code I sent ). This is
to make sure the grouping is sorted also.

So in the first pass , you get the <output> nodes and they are not numbered.
Store the whole set in a variable. The variable now has a result tree
fragment that looks like 

<outputs>
        <output>250</output>
        <output>250</output>
        <output></output>
        <output>300</output>
        <output></output>
</outputs>

Now you can see that traversing through this RTF ( result tree fragment) can
print the right row value ( using position() function ) .. 


I used xalan's node-set extention. You can use the other exslt extentions or
saxon extentions or what ever you are using.

Hope this helps.
Vasu Chakkera

-----Original Message-----
From: Vasu Chakkera [mailto:vasucv(_at_)hotmail(_dot_)com] 
Sent: Tuesday, May 29, 2007 11:15 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] Grouping and Numbering

This should work..
Carl, let me know if this solves your issues

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xalan="http://xml.apache.org/xalan";

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
        <xsl:key match="//group_id" name="groupid"
use="normalize-space(text())"/>
        <xsl:template match="/">
                <xsl:variable name="outputs">
                        <outputs>
                                <xsl:for-each
select="//group_id[generate-id(.) =
generate-id(key('groupid',normalize-space(.))[1])]">
 
                                        <xsl:for-each
select="key('groupid',normalize-space(text()))">
                                                <output>
                                                        <xsl:value-of
select="."/>
                                                </output>
                                        </xsl:for-each>
                                        <output>
</output>
                                </xsl:for-each>
                        </outputs>
                </xsl:variable>
                <outputs>
                        <xsl:for-each
select="xalan:nodeset($outputs)/outputs/output">
                                <output row = "{position()}">
                                        <xsl:value-of select="."/>
                                </output>
                        </xsl:for-each>
                </outputs>
        </xsl:template>
</xsl:stylesheet>

-----Original Message-----
From: Mukul Gandhi [mailto:gandhi(_dot_)mukul(_at_)gmail(_dot_)com] 
Sent: Friday, May 25, 2007 10:25 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Grouping and Numbering

I find this problem rather difficult to solve with pure XSLT 1.0. This
is due to the fact, that XSLT doesn't allow to maintain variable
state. If you are willing to write extension functions (for e.g. in
Java), it's easier to solve this problem.

Please consider the following example.

Java extension class:

public class Iterator
{
   private static int i = 0;

   public static int next()
   {
     i++;
     return i;
   }
}

XSLT stylesheet:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                       xmlns:java="http://xml.apache.org/xalan/java";
                       exclude-result-prefixes="java"
                       version="1.0">

  <xsl:output method="xml" indent="yes" />

  <xsl:key name="by-group" match="result" use="details/group_id" />

  <xsl:template match="sample">
    <sample>
      <xsl:for-each select="result[generate-id() =
generate-id(key('by-group', details/group_id)[1])]">
        <xsl:sort select="details/group_id" data-type="number" />
        <xsl:variable name="x" select="position()" />
        <xsl:for-each select="key('by-group', details/group_id)">
          <output row="{java:Iterator.next()}"><xsl:value-of
select="details/group_id" /></output>
        </xsl:for-each>
        <xsl:if test="$x != last()">
          <output row="{java:Iterator.next()}" />
        </xsl:if>
      </xsl:for-each>
    </sample>
  </xsl:template>

</xsl:stylesheet>

Using Xalan-J (ver 2.7.0), when the above stylesheet is applied to the XML:

<sample>
   <result>
     <details>
       <group_id>250</group_id>
     </details>
   </result>
   <result>
     <details>
       <group_id>300</group_id>
     </details>
   </result>
   <result>
     <details>
       <group_id>250</group_id>
     </details>
   </result>
</sample>

The output produced is:

<?xml version="1.0" encoding="UTF-8"?>
<sample>
  <output row="1">250</output>
  <output row="2">250</output>
  <output row="3"/>
  <output row="4">300</output>
</sample>

PS: The stylesheet uses Muenchian method to do grouping. I am also
keen to know, is there any way, this problem can be solved with pure
XSLT 1.0.

On 5/25/07, Carl Radley <Carl(_dot_)Radley(_at_)stl-ltd(_dot_)com> wrote:
Hi,
I'm using XSLT version 1, so can't use grouping.

I need to run through a large structure that resembles:
<sample>
   <result>
       <details>
         <group_id>250</group_id>
       </details>
   </result>
   <result>
       <details>
         <group_id>300</group_id>
       </details>
   </result>
   <result>
       <details>
         <group_id>250</group_id>
       </details>
   </result>
</sample>

Firstly, I need to sort the data into <group_id> order, so I use:
<xsl:apply-templates select="sample//result/details">
   <xsl:sort select="group_id" data-type="number" />
</xsl:apply-templates>

Next, within the called template, I need to loop through all the <details>
and add row numbering information but add an extra row at the end of each
group.
So hope to see:
<output row="1">250</output>
<output row="2">250</output>
<output row="3" />
<output row="4">300</output>

First problem is that, when I check "preceding::details[1]/group_id" it
refers to the original document layout and not the sorted order, so I get:
<output row="1">250</output>
<output row="2" />
<output row="3">250</output>
<output row="4" />
<output row="5">300</output>

Second problem is remembering the row count, since I need to add several
additional rows during the loop, so "position()" goes out of sync.
I've tried to call another template, passing in the <group_id> and
determine it's sorted position but have not been able to get a unique list
because of my first problem.

Hope I've made this as concise as possible.
Thanks in advance,
Carl


----------------------------------------------------------------
This e-mail (which includes any files attached to it) is not
contractually binding on its own, it is intended solely for
the named recipient and may contain CONFIDENTIAL, legally
privileged or trade secret information protected by law.
If you have received this message in error please delete it
and notify us immediately by telephoning +44(0)2476421213.
If you are not the intended recipient you must not use, disclose,
distribute, reproduce, retransmit, retain or rely on any
information contained in this e-mail. Please note that Severn
Trent Laboratories Limited reserve the right to monitor email
communications in accordance with applicable law and regulations.

To the extent permitted by law, neither Severn Trent Laboratories
Limited or any of its subsidiaries, nor any employee, director
or officer thereof, accepts any liability whatsoever in relation
to this e-mail including liability arising from any external breach
of security or confidentiality or for virus infection or for statements
made by the sender as these are not necessarily made on behalf of
Severn Trent Laboratories Limited.

Severn Trent Laboratories Limited is a limited company registered in
England and Wales under registered number 2148934 with its registered
office at 2297 Coventry Road, Birmingham B26 3PU.


-- 
Regards,
Mukul Gandhi

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--