RE: [xsl] Sorting and Paging in one pass with XSLT 2

Subject: RE: [xsl] Sorting and Paging in one pass with XSLT 2
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 19 Nov 2004 05:02:41 -0000
I think that any solution is likely to put the sorted results in memory
before splitting it into multiple result trees, so you shouldn't be worrying
too much about a two-pass solution. If your intermediate result is a
sequence of nodes, rather than a tree, then it should be reasonably
efficient, because the intermediate sequence will contain references to the
original nodes, rather than copies.

Try

    <xsl:template match="result">
        <xsl:variable name="sorted-rows" as="element(row)*>
          <xsl:perform-sort select="row">
            <xsl:sort select="lname"/>
            <xsl:sort select="fname"/>
          </xsl:perform-sort>
        </xsl:variable>
        <xsl:for-each-group select="$sorted-rows"
                            group-adjacent="position()-1 idiv $perPage">
            <xsl:result-document href="out{current-grouping-key()}.xml">
                <result>
                    <xsl:copy-of select="current-group()"/>
                </result>
            </xsl:result-document>
        </xsl:for-each-group>
    </xsl:template>

I'd be interested to know how this performs.

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

> -----Original Message-----
> From: Kyle Himmerick [mailto:kyle@xxxxxxxxxxxx] 
> Sent: 19 November 2004 03:26
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Sorting and Paging in one pass with XSLT 2
> 
> Hello All,
> 
> I am trying to use some of the new XSLT 2 functionality to improve my 
> sorting and paging performance.
> 
> Ideally I would be able to sort and splice a large document 
> tree in one 
> pass.
> 
> So sort the tree and put x # of records in each result document.
> 
> Here's a pseudo of what I'm trying to do:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
> xmlns:fo="http://www.w3.org/1999/XSL/Format";>
>    <xsl:param name="perPage" select="number('10')"/>
> 
>    <xsl:template match="result">
>        <xsl:for-each select="row">
>            <xsl:sort select="lname"/>
>            <xsl:sort select="fname"/>
>            <xsl:variable name="page" 
> select="ceiling(position()/$perPage)"/>
>            <xsl:result-document href="out{$page}.xml">
>                <result>
>                    <xsl:copy-of select="."/>
>                </result>
>            </xsl:result-document>
>        </xsl:for-each>
>    </xsl:template>
> </xsl:stylesheet>
> 
> Obviously this won't work as it would try create a new 
> result-document 
> on each pass.  Whereas I need the first $perPage rows to go into the 
> same result-document.
> 
> I was hoping to find a way to use the grouping functionality 
> in xslt 2.  
> Possibly grouping records by their page and then iterate through 
> creating a new result-document for each group of records.  I couldn't 
> find a way to do this with one pass through the document, 
> which is what 
> I'm trying to stick with since I can potentially have very large 
> incoming xml.
> 
> Any ideas or suggestions for implementing an efficient method 
> of sorting 
> and then paging the results?
> 
> Best Regards,
> Kyle

Current Thread