XSLT来做分页确实不是怎么好做,但如果做了,会发现其实也很简单,先看下效果图:
如果是直接对一个XML文件分页也就罢了,但如果数据量很大的话,总不能一次都取过来吧,过于庞大的XML运算起来那速度相信没有多少客户能忍受的。
再来回忆一下XSL的一些元素:
<xsl:template> 元素
<xsl:template> 元素用于构建模板。
match 属性用于关联 XML 元素和模板。match 属性也可用来为整个文档定义模板。match 属性的值是 XPath 表达式(举例,match="/" 定义整个文档)。
name 属性用于为模板起一个名字,以方便在需要时定位模板。
先建立一个xml文件,名为tamplate.xml,然后来试试template都有什么作用:
tamplate.xml:
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="template.xslt"?>
<?xml-style?>
<root>
<message>Hello Angel</message>
</root>
此模板用于匹配整个xml文档,现在它的作用仅仅是直接输出其中的xhtml,我们将通过它来调用另一个模板,可以认为就像在C#中通过Main方法调用其它方法一样:
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Template</title>
</head>
<body>
</body>
</html>
</xsl:template>
接下来我们要使用另一个模板来输出文档中<message>节点的内容:
<xsl:template name="hello">
<div xmlns="http://www.w3.org/1999/xhtml">
<h1>
<xsl:value-of select="/root/message"/>
</h1>
</div>
</xsl:template>
这里message节点只有一个,并且我们只为此模板定义了name属性,所以将用到XSL中的另一个元素来调用:
<xsl:call-template> 元素
<xsl:call-template> 元素可把一个模板插入到当前调用位置,其通过模板的name属性来寻找合适的模板。
如果两个模板在同一个文件中声明,只需要在match="/"的模板中合适的位置放入如下代码,便可以将此模板中的内容加入到所调用位置,在这里建议放入<page>元素中:
<xsl:call-template name="hello"></xsl:call-template>
在调用模板的时候还可以传递参数,传入方式是使用<xsl:with-param>元素,我们可以将此参数放置到<xsl:call-template>元素中。
<xsl:with-param name="param">The Param</xsl:with-param>
<xsl:param> 元素
<xsl:param> 元素可接收外部传入的参数。
在上面调用<xsl:template name="hello">这个模板的时候已经传入了名为“param”的参数,接收方式也很简单,将下面的代码放入“Hello”模板的开始部位就可以了:
<xsl:param name="param"></xsl:param>
使用param的方式是在param的名字前面加“$”符号,当然,param并不仅仅能在<xsl:value-of>元素中使用:
<h2>
<xsl:text>Param:</xsl:text>
<xsl:value-of select="$param"/>
</h2>
<xsl:text> 元素
<xsl:text> 元素可把一段文本插入当前位置。
那么下面这段代码和直接写“Param:”其实结果是一样的:
<xsl:text>Param:</xsl:text>
完整的xslt文件内容如下,其中<!DOCTYPE>元素建议直接交给<xsl:output>元素来实现:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Template</title>
</head>
<body>
<xsl:call-template name="hello">
<xsl:with-param name="param">The Param</xsl:with-param>
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="hello">
<xsl:param name="param"></xsl:param>
<div xmlns="http://www.w3.org/1999/xhtml">
<h1>
<xsl:value-of select="/root/message"/>
</h1>
<h2>
<xsl:text>Param:</xsl:text>
<xsl:value-of select="$param"/>
</h2>
</div>
</xsl:template>
</xsl:stylesheet>
<xsl:apply-templates> 元素
<xsl:apply-templates> 元素可把一个模板应用于当前的元素或者当前元素的子节点。
当样式需要重复应用时,可以考虑用<xsl:apply-templates>元素,下面建立下个模板,用于<xsl:apply-templates>元素调用:
<xsl:template match="message">
<h1xmlns="http://www.w3.org/1999/xhtml">
<xsl:value-of select="text"/>
</h1>
</xsl:template>
针对下面的XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="templates.xslt"?>
<messages>
<message>
<text>Dear Angel</text>
</message>
<message>
<text>My Angel!</text>
</message>
<message>
<text>I LOVE YOU !!</text>
</message>
</messages>
调用方法如下:
<xsl:apply-templates select="messages/message"></xsl:apply-templates>
接下来再看一下另一个元素:
<xsl:choose> 元素
<xsl:choose> 元素用于结合 <xsl:when> 和 <xsl:otherwise> 来表达多重条件测试。
为了方便测试XSLT文件,还是建立了如下XML:
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="choose.xslt"?>
<condition>3</condition>
可以先将XSLT的<xsl:choose>想象成C#中的多分支if语句:
<xsl:choose>
<xsl:when test="condition=1">
<h1>Condition is: 1</h1>
</xsl:when>
<xsl:when test="condition=2">
<h1>Condition is: 2</h1>
</xsl:when>
<xsl:otherwise>
<h1>I do not know what the condition is.</h1>
</xsl:otherwise>
</xsl:choose>
只有当<xsl:when>元素的test被满足时,才会执行其中的语句,如果没有任何一个<xsl:when>满足,则<xsl:otherwise>被执行。
做分页用上面的知识应该已经够了。分页的思想是将 分页相关的信息全部写入XML文件中,然后通过<xsl:template>元素建立模板,依靠<xsl:call-template>、<xsl:applay-template>来调用相关的模板,使用<xsl:choose>进行条件过滤。
根据上面的经验,把分页信息放到xml文件中的话,我们就可以开始使用xslt来做分页了。
这里最需要注意的是我把<html>元素中的<script>、<link>元素都放到一个模板中了,并且加了xml:space="preserve"标记来表明需要保留空白处,是为了保证在转换时不至于被转换成为自动闭合标签或没有结束标记的标签导致浏览器无法解析。
写上与<xtml>标记一样的xmlns就不用说明为什么了吧?如果不写的话,默认的命名空间没有指定的话就是空白。会生成xmlns=""的内容。所以每个最外层的元素最好都要写xmlns,当然,如果调用者的xmlns与被调用模板的xmln相同的话,内部元素的xmlns就不会被保留,这是因为它们本就是同一个命名空间的。总之,是xml语法决定的。谁让给<html>加了 xmlns="http://www.w3.org/1999/xhtml"的命名空间呢。
<xsl:template name="headInclude" xml:space="preserve">
<link rel="stylesheet" type="text/css" href="Content/Site.css" xmlns="http://www.w3.org/1999/xhtml"> </link>
<script src="Scripts/jquery-1.6.4.min.js" type="text/javascript" xmlns="http://www.w3.org/1999/xhtml"> </script>
<script src="Scripts/pager.js" type="text/javascript" xmlns="http://www.w3.org/1999/xhtml"> </script>
</xsl:template>
好了,不管BUG有多少,没有时间去细细测试,直接上代码了: