使用 XSLT 创建分页按钮






4.75/5 (8投票s)
2004年1月5日
3分钟阅读

79197

1130
演示如何将 XML 文件拆分为页面,
引言
当显示大量数据时,有时需要将数据分成页面。在本文中,我将展示如何使用 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
参数用于显示正确的数据页面并创建指向其他页面的相应链接。转换样式表的其他可选参数是 PageSize
和 MaxPages
。PageSize
是每页显示的项目数。 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 创建基于字母的分页。如果有人有实际需要,请给我留言。感谢您的关注,请记住,您的意见非常重要。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。