Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 3rd, 2007, 11:20 PM
Registered User
 
Join Date: Jun 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Default Grouping and Pagination

Hello,

I'm new to XSLT and I would like to ask if it is possible to do pagination after grouping of records?

I'm using XSLT 1.0. I use a c# program to get records from a DB and return a xml file contains records of articles. All the formattings will be done by the XSLT. The records need to be grouped and sorted according to their authors or categories, etc. Each page shows 10 records. The following is the output format that I want to have.

(Page 1)

Author A
Article 3
Article 7
Article 18
Article 20

Author B
Article 1
Article 30
Article 40
Article 41

Author C
Article 5
Article 8

Next Page >>

----------------------------------------------------

(Page 2)

Author C
Article 21
Article 26

Author D
Article 25
Article 60

<< Previous Page


I succeeded in grouping of results and I know how to do pagination when there is no Grouping. however I do not have idea on how to combine grouping and pagination.

Thanks in advance.
 
Old June 4th, 2007, 01:40 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Well it maybe better to group and paginate in the underlying query but if you want to do it in the XSLT stage then you need to first group. If you're using XSLT 1.0 then you need to look at Muenchian grouping, there's a link on the first post in this forum, if using version 2.0 then you can use xsl:for-each-group.
The pagination will act on the grouped records and will need two parameters in the stylesheet, one that holds the number of records per page and the other which page you wish to display. You then use these two values to only show the records that are in the range calculated by:
First record = ($recordsPerPage * ($pageNumber - 1)) + 1
Last record = ($recordsPerPage * $pageNumber)


--

Joe (Microsoft MVP - XML)
 
Old June 4th, 2007, 03:25 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I think this kind of thing is best done in a multi-pass transformation (sometimes called a pipeline). First do the grouping, then apply pagination to the result. You can do this in two separate stylesheets, or you can do it in a single stylesheet provided (in 1.0) that you have the xx:node-set() extension to make the output of the first pass accessible for processing by the second. Separate stylesheets makes the code more reusable and modular, but can be a bit more difficult to deploy depending on the environment you are running in.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 4th, 2007, 04:42 AM
Registered User
 
Join Date: Jun 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you for the replies.
The environment for me to run this program is difficult to have separate stylesheets and I wish to do it in a single stylesheet.

I have read about Muenchian grouping and able to group the records by Author/Category.

Here is part of the codes in the XSLT regarding the grouping of articles. (I hope this is enough, if not, I'll show more next time.)

Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:key name="rows" match="Record" use="author" />



<xsl:template match="ArticleRecords">
    <xsl:apply-templates select="Record[generate-id(.) = generate-id(key('rows', author)[1])]">
        <xsl:sort select="author"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="Record">
    <xsl:for-each select="key('rows', author)">
        <xsl:value-of select="title"/>
        <xsl:value-of select="author"/>
    </xsl:for-each>
</xsl:template>
The above codes is for the grouping of author and it works.
I know how to do pagination if there's no grouping. However I don't know how to combine them.

Michael said that it can be done with xx:node-set(), where should I put this inside my code?

Thanks in advance.
 
Old June 4th, 2007, 04:53 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The general pattern for doing a multi-phase transformation within a single stylesheet is:

<xsl:template match="/">
  <xsl:variable name="r1">
    <xsl:apply-templates mode="phase1"/>
  </xsl:variable>
  <xsl:variable name="r2">
    <xsl:apply-templates select="xx:node-set($r1)" mode="phase2"/>
  </xsl:variable>
  <xsl:apply-templates select="xx:node-set($r2)" mode="phase3"/>
</xsl:template>

Here xx:node-set() represents whatever node-set() extension function is available in your chosen processor.

Of course one of the phases can be done in the default mode, or they can all be done in the default mode if none of the template rules conflict.


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 4th, 2007, 05:26 AM
Registered User
 
Join Date: Jun 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Does this means that I can:
1. do grouping first,
2. store the grouped records as r1, and,
3. group every 10 records in r1?

For example:

<xsl:for-each select="exsl:node-set($r1)/*[position() mod 10 = 1]">
        <xsl:copy-of select=".|following-sibling::*[position() &lt; 10]"/>
</xsl:for-each>

Is this correct?
 
Old June 4th, 2007, 07:22 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Yes, that looks about right.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 4th, 2007, 11:04 PM
Registered User
 
Join Date: Jun 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I still cannot figure it out, it still shows all records instead of 10 records...

The xml source file:
Code:
<ArticleRecords>
  <Record>
    <ID>9</ID>
    <TITLE>Some Article Title</TITLE>
    <AUTHOR>Author A</AUTHOR>
    <DESCRIPTION>Some Article Description</DESCRIPTION>
    <PUBLISHDATE>2007-02-15</PUBLISHDATE>
  </Record>
  <Record>
    <ID>17</ID>
    <TITLE>Another Article Title</TITLE>
    <AUTHOR>Author B</AUTHOR>
    <DESCRIPTION>Another Article Description</DESCRIPTION>
    <PUBLISHDATE>2007-02-15</WRITE>
  </Record>
</ArticleRecords>
The xslt part regarding article records:
Code:
<xsl:template match="ArticleRecords">
    <xsl:apply-templates select="Record[generate-id(.) = generate-id(key('rows', author)[1])]">
        <xsl:sort select="author"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="Record">
    <b><xsl:value-of select="author"/></b>
    <xsl:variable name="groupedrecords">
        <xsl:for-each select="key('rows', author)">
            <xsl:call-template name="showrecord" />
        </xsl:for-each>
    </xsl:variable>
    <xsl:for-each select="exsl:node-set($groupedrecords)/*[position() mod 10 = 1]">
        <xsl:copy-of select=".|following-sibling::*[position() &lt; 10]"/>
    </xsl:for-each>
</xsl:template>

Thanks in advance.
 
Old June 5th, 2007, 02:47 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Since "author" is upper-case in your XML and lower-case in your stylesheet, I'm surprised that this is displaying anything at all.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 5th, 2007, 03:49 AM
Registered User
 
Join Date: Jun 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Actually that was the code of my last trial...
I have tried both uppercase and lowercase.
The problem seems to be at here:

Code:
<xsl:for-each select="exsl:node-set($groupedset)/*[position() mod 10 = 1]">
   <xsl:copy-of select=".|following-sibling::*[position() < 10]"/>
</xsl:for-each>
I'm trying to figure out what the problem is...





Similar Threads
Thread Thread Starter Forum Replies Last Post
Protect cells and allow grouping/un-grouping sfreuden Excel VBA 4 December 14th, 2006 08:01 AM
grouping and pagination sasidhar79 Crystal Reports 1 December 6th, 2005 01:12 PM
pagination Regornil Pro JSP 2 May 31st, 2005 06:10 AM
Please.....Pagination junemo PHP Databases 2 September 25th, 2004 01:14 PM
pagination junemo Oracle 0 July 1st, 2004 04:07 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.