65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XSLT 创建分页按钮

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (8投票s)

2004年1月5日

3分钟阅读

viewsIcon

79197

downloadIcon

1130

演示如何将 XML 文件拆分为页面,并使用 XSL 转换样式表渲染页面链接。

Sample image

引言

当显示大量数据时,有时需要将数据分成页面。在本文中,我将展示如何使用 XSL 转换样式表创建基于数字的分页。对于此示例,我将从 XML 格式的 Northwind 数据库中获取数据。以下是数据文件的一个摘录。

<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>

根元素是 <Northwind>,详细信息存储在多个 <Products> 中。

创建基于数字的分页

页面按钮被创建为带有参数的链接,其中页面编号作为 URL 的一部分传递,即 default.aspx?page=5。在代码中创建此类链接的一种方法在 此处 描述。但当前文章的目的是使用纯 XSL 转换创建这些链接。转换应用于在 System.Web.UI.WebControls.Xml 控件中,该控件在 default.aspx 中创建为

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

XML 源从 northwind_products.xml 加载,XSL 转换样式表从 default.xslt 加载。在继续进行转换样式表之前,我需要在 Page_Load 处理程序中指出以下代码。此代码获取 ?page= 参数,创建 XsltArgumentList 并将 CurrentPage 参数传递给转换。

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;

CurrentPage 参数用于显示正确的数据页面并创建指向其他页面的相应链接。转换样式表的其他可选参数是 PageSizeMaxPagesPageSize 是每页显示的项目数。 MaxPages 定义最大页面链接数。

当前页面的按钮不显示为链接。例如,如果 CurrentPage=50 并且 MaxPages=5,那么我们将得到以下结果:“第一页 ... [48] [49] [50] [51] [52] ... 最后一页”,其中“[50]”是一个没有链接的按钮。渲染按钮的 XSL 模板如下所示

<!-- 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>

这段代码的有趣部分是选择适当的节点的地方。第一步是选择每个页面的一个节点 - 相关的 XPath 表达式是 Products[((position()-1) mod $PageSize = 0)]。结果集将包含与页面一样多的元素。第二步是只选择其中的 $MaxPages,它们环绕 $CurrentPage。最后,结果使用 position() 语句呈现。为了减小此示例的大小,我省略了创建链接的部分代码,但您可以从 <xsl:value-of select="position()"/> 语句中了解其实现方式。

根据页码过滤数据

显示表的 模板 非常简单

<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>

选择相应页面数据的 XPath 表达式以粗体显示。请注意,产品名称存储为一个属性,这意味着我们将使用 @ProductName 语句来选择它。

关注点

毫无疑问,存在更简单的创建页面按钮的方法,例如考虑 DataGrid。但要考虑可移植性。在本文中,我仅使用 C# 将参数传递给 XSLT 解析器,但 XSLT 解析器存在于各种编程语言和平台上。希望我的代码对那些关心兼容性和可移植性的人有所帮助。也可以使用 XSLT 创建基于字母的分页。如果有人有实际需要,请给我留言。感谢您的关注,请记住,您的意见非常重要。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.