在处理大量数据时,将数据分页显示是一种常见的需求。本文将展示如何使用XSL Transformation样式表创建基于数字的分页。以XML格式的Northwind数据库数据为例,以下是数据文件的一部分:
<Northwind>
<Products>
<ProductName>Chai</ProductName>
<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
,则将得到以下结果:"First ... [48] [49] [50] [51] [52] ... Last"
,其中[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>
<xsl:when test="(position() > ($CurrentPage - ceiling($MaxPages div 2)) or position() > (last() - $MaxPages)) and ((position() < $CurrentPage + $MaxPages div 2) or (position() < 1 + $MaxPages))">
<xsl:if test="position()=$CurrentPage">
[<xsl:value-of select="position()"/>]
</xsl:if>
<!-- skipped code which creates links -->
</xsl:when>
</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))">
<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创建基于字母的分页。如果有人有实际需要,请给留言。感谢兴趣,记住意见非常宝贵。