5,448,416 members and growing! (17,220 online)
Email Password   helpLost your password?
Languages » XML » XSLT     Intermediate

Creating page link buttons with XSLT

By Igor Gribanov

Shows how to split an XML file into pages and render page links using XSL Transformation style sheet.
C++/CLI, C#, VB, XMLWindows, .NET, .NET 1.0, .NET 1.1, Win2K, WinXP, Win2003, ASP, ASP.NET, Visual Studio, Dev

Posted: 4 Jan 2004
Updated: 4 Jan 2004
Views: 38,235
Bookmarked: 16 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
6 votes for this Article.
Popularity: 3.07 Rating: 3.94 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 16.7%
3
0 votes, 0.0%
4
5 votes, 83.3%
5

Sample image

Introduction

When displaying large sets of data, it is sometimes necessary to split data into pages. In this article, I will show how to create a number-based paging by using the XSL Transformation style sheet. For this example, I will take data from the Northwind database in XML format. Below is an excerpt from the data file.

<Northwind>
    <Products ProductName="Chai">
        <ProductID>1</ProductID>
        <SupplierID>1</SupplierID>
        <CategoryID>1</CategoryID>
        <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>
        <UnitPrice>18.0000</UnitPrice>
        <UnitsInStock>39</UnitsInStock>
        <UnitsOnOrder>0</UnitsOnOrder>
        <ReorderLevel>10</ReorderLevel>
        <Discontinued>false</Discontinued>
    </Products> 
</Northwind>

The root element is <Northwind> and the details are stored within the number of <Products>.

Creating number-based paging

The page buttons are created as links with parameters where page numbers are passed as a part of the URL, i.e. default.aspx?page=5. One way to create such links in code is described here. But the goal of the current article is to create those links using pure XSL transformation. The transformation is applied within the System.Web.UI.WebControls.Xml control, which is created in the default.aspx as:

<asp:Xml id="Xml1" runat="server" 
DocumentSource="northwind_products.xml" 
TransformSource="default.xslt"></asp:Xml>

The XML source is loaded from the northwind_products.xml, and the XSL Transformation style sheet is loaded from the default.xslt. Before we proceed to the transformation style sheet, I need to point out the following code in the Page_Load handler. This code takes the ?page= parameter, creates XsltArgumentList and passes CurrentPage parameter to the transformation.

double CurrentPage = 1D;
if(Request.Params["page"] != null) 
    CurrentPage = Double.Parse(Request.Params["page"]);
XsltArgumentList xal = new XsltArgumentList();
xal.AddParam("CurrentPage", String.Empty, CurrentPage);
Xml1.TransformArgumentList = xal;

The CurrentPage parameter is required to display the correct page of data and to create the appropriate links to other pages. Other optional parameters of the transformation style sheet are PageSize and MaxPages. PageSize is the number of items displayed per page. MaxPages defines the maximum number of page links.

The button for a current page is not displayed as a link. For example, if the CurrentPage=50 and MaxPages=5, then we will get the following result: "First ... [48] [49] [50] [51] [52] ... Last", where "[50]" is a button without a link. The XSL template, which renders the buttons is provided below:

<!-- displays page buttons -->
<xsl:template name="Pages">
<xsl:variable name="TotalItems" select="count(Products)" />
<xsl:variable name="Pages" select="ceiling($TotalItems div $PageSize)" />

<!-- select first element of each page -->
<xsl:for-each select="Products[((position()-1) mod $PageSize = 0)]">
    <!-- display the appropriate portion of page links -->
    <xsl:choose>
        <!-- the expression below selects only MaxPages number of pages -->
        <xsl:when test="(position() > ($CurrentPage - ceiling($MaxPages div 2)) or 
        position() > (last() - $MaxPages)) and 
        ((position() < $CurrentPage + $MaxPages div 2) or 
        (position() < 1 + $MaxPages))">

        <!-- render non-link page button for CurrentPage -->
        <xsl:if test="position()=$CurrentPage">
        [ <xsl:value-of select="position()"/> ]
        </xsl:if>

        <!-- skipped code which creates links -->

        </xsl:choose>
</xsl:for-each>
</xsl:template>

The interesting part of this code is where the appropriate nodes are selected. The first step is to select one node of each page - the related XPath expression is Products[((position()-1) mod $PageSize = 0)]. The resulting set will contain as many elements as there are pages. The second step is to pick only $MaxPages of them, which surround the $CurrentPage. Finally, the result is rendered using the position() statement. To reduce the size of this example, I have excluded part of the code which creates links, but you can get the idea about how it is done from the <xsl:value-of select="position()"/> statement.

Filtering the data according to page number

Template, which displays the table is rather simple:

<xsl:template match="Products">
<xsl:choose>
    <xsl:when test="(position() >= 1 + ($CurrentPage - 1) * $PageSize) and 
    (position() < (1 + $CurrentPage * $PageSize))">

    <!-- display table rows here -->
    <tr>
    <td><xsl:value-of select="position()"/></td>
    <td><xsl:value-of select="@ProductName"/></td>
    <td><xsl:value-of select="format-number(UnitPrice,'$#.00')"/></td>
    <td align="center"><xsl:value-of select="UnitsInStock"/></td>
    </tr>

</xsl:when>
</xsl:choose>
</xsl:template>

The XPath expression which selects data of the appropriate page is highlighted in bold. Note that product name is stored as an attribute, which means that we will use @ProductName statement to select it.

Points of Interest

No doubt that there exists a simpler way of creating page buttons, consider DataGrid for example. But think of portability. In this article, I have used C# only to pass an argument to XSLT parser, but XSLT parsers exist in various programming languages and platforms. Hopefully, my code will be useful to those, who are concerned about compatibility and portability. Also it is possible to create a letter-based paging with XSLT. If anyone has a practical need for it, please drop me a line. Thank you for your interest and remember that your opinions are highly appreciated.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Igor Gribanov


I am highly qualified and have experience in programming applications for Windows and web, database development, legacy software integration, technical writing and consulting. Since the beta release I have been working with .NET technologies: C#, VB.NET, MSIL. My other skills include XML/XSLT, Crystal Reports and SQL Server 2000.
dotnet@bk.ru
Occupation: Web Developer
Location: Russian Federation Russian Federation

Other popular XML articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 4 of 4 (Total in Forum: 4) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralWOW!!!memberGarwick21:48 29 Aug '07  
GeneralYou are GOOD!! Aren't you?!sussAnonymous9:19 5 Jan '04  
GeneralRe: You are GOOD!! Aren't you?!memberIgor Gribanov9:59 5 Jan '04  
GeneralRe: You are GOOD!! Aren't you?!sussAnonymous5:42 6 Jan '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jan 2004
Editor: Smitha Vijayan
Copyright 2004 by Igor Gribanov
Everything else Copyright © CodeProject, 1999-2008
Web19 | Advertise on the Code Project