Xsl模板应用基础(三、模板嵌套)

左图是常见的页面布局图,具有相当普遍的使用量与代表意义,本文使用 XSL 打造这种布局的模板框架。

左图的特点是 Header、Sidebar、Footer 三个区域是公共区域,一个普通网站大部分页面都可以抽象出这三个区域,不同的页面只在 Body 区域有差异。那么在制作页面时只要编写 Body 区域,其他位置只要调用(include)公共的 Header、Sidebar、Footer区域就算完成页面了。这是正向思维,因为程序里面经常这么干,功能模块化,按需加载。用这种思路做网页模板,前端人员会抓狂,因为这种框架明显忽视了前端HTML结构的完整性与合理性,CSS、Javascript变得混乱不堪。

用Xsl打造模块框架,使用的恰好是反向思维。设计框架模板的作用是使每个页面都继承自模板,子页面又能重写扩展公共区域。既节省时间重用模块,又能体现灵活性。反向思路的原理是:编写的每个页面是框架模板的一个区域,当前页面被主框架调用,而不是主动调用其他区域。按照左图所示,先编写框架,仅包含 Header、Sidebar、Footer三大区域,Body区域的位置留空,调用一个固定名称的 <xsl:template name="main">...</xsl:template>,元素的名称定为main是约定,以后每个子页面都必须包含此元素。

为了不致概念混乱,xsl文件我们称为网页模板,xsl文件中的 <xsl:template> 直接呼作 template元素,它类似于程序中方法、函数的概念,有名称,且接受参数。

首先打造根级的网页模板,文件名为:mainframe.xsl,主要代码如下:

 1 <html> 
 2     <head> 
 3         <title>主框架</title> 
 4     </head> 
 5     <body> 
 6         <div class="box"> 
 7             <div class="header">Header</div> 
 8             <div class="body"> 
 9                 <div class="main"> 
10                     <xsl:call-template name="main" /> 
11                 </div> 
12                 <div class="sidebar">Sidebar</div> 
13             </div> 
14             <div class="footer">Footer</div> 
15         </div> 
16     </body> 
17 </html> 

上例中仅main元素是变量,其他部分都是确定的静态值,进一步抽象,把静态的 Header、Sidebar、Footer 以及 title 元素(下面需要用到)保存到另一个网页模板文件中去:common.xsl:

 1 <xsl:template name="header"> 
 2     Header 
 3 </xsl:template> 
 4 
 5 <xsl:template name="sidebar"> 
 6     Sidebar
 7 </xsl:template> 
 8 
 9 <xsl:template name="footer"> 
10     Footer 
11 </xsl:template> 
12 
13 <xsl:template name="pagetitle"> 
14     主框架的标题 
15 </xsl:template> 
16
17 <!--空白的 main -->
18 <xsl:tempate name="main"/>

mainframe.xsl 于是修改为:

 1  <xsl:import href="common.xsl" />  
 2  ...... 
 3  <xsl:template match="/">
 4      <html> 
 5      <head> 
 6          <title><xsl:call-template name="pagetitle" /></title> 
 7      </head> 
 8      <body> 
 9          <div class="box"> 
10          <div class="header"> 
11              <xsl:call-template name="header" /> 
12          </div> 
13          <div class="body"> 
14              <div class="main"> 
15              <xsl:call-template name="main" /> 
16              </div> 
17              <div class="sidebar"> 
18              <xsl:call-template name="sidebar" /> 
19              </div> 
20          </div> 
21          <div class="footer">
22              <xsl:call-template name="footer" />
23          </div> 
24          </div> 
25      </body>
26      </html>
27  </xsl:template>

mainframe.xsl 只承担了整体排版布局,定义全局CSS、Javascript,定义默认的Header、Sidebar、Footer,它与Body区域无关。 其中 Body 区域调用了一个名为 main 的template元素。在 common.xsl 文档中定义了一个内容空白的名为 main 的 template元素,但实际上该区域不可能为空,因此在以后要做的每个页面(产品页、新闻页、用户后台等等)中,都必须再次定义一个名为 main 的template元素,用作覆盖定义。比如新闻列表页的XSL主要代码如下(文件名为list.xsl):

1 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
2 <xsl:import href="mainframe.xsl"/> 
3 
4 <xsl:template name="main"> 
5     此处是新闻列表页 
6 </xsl:template> 
7 
8 </xsl:stylesheet> 

上面有两处地方需要注意,第一是必须在 xsl 文件的开头载入主框架(主框架又载入 common.xsl),其次是此页面默认入口是名为 main 的 template,list.xsl文件中不能存在自动匹配的template元素(如 <xsl:tempate match="/">,因为该元素与存在于mainframe.xsl中)。list.xsl 中的 main 元素是为主框架准备的,制作新闻列表页,完全无需考虑Header、Sidebar、Footer等区域的数据与表现,如果使用C#转换新闻XML数据与list.xsl,得到的HTML却包含了完整的 Header、Body、Sidebar、Footer区域。这个过程,相当于比较粗糙地实现了模板的继承。

网页的标题(title元素)是在mainframe中定义的,但每个页面的标题可能都不同,这就需要在Xsl文件中重写名为pagetitle的template元素,用以覆盖common.xsl中的默认值。list.xsl 文件改动如下:

 1 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 2     <xsl:import href="mainframe.xsl"/> 
 3 
 4     <xsl:template name="main"> 
 5     此处是新闻列表页 
 6     </xsl:template> 
 7 
 8     <xsl:template name="pagetitle"> 
 9     列表页的标题 xxxx
10     </xsl:template> 
11 
12 </xsl:stylesheet> 

上面简单地实现了模板重载。

 

Xsl的一些坑:

1、必须使用 xsl:import 元素导进来的模板才可以使用同名template元素覆盖默认的定义,如果使用 xsl:include 引入,将产生错误:"不能使用相同导入优先权多次定义命名模板"。
2、使用前面文章介绍的方法,C#编译list.xsl时会把mainframe.xsl与common.xsl当做list.xsl文件中的一部分,如果list.xsl文件不动,仅修改mainframe.xsl与common.xsl两个文件,list.xsl依赖的缓存不会被回收(因为没有依赖前面的2个xsl文件)。
3、在Xsl文件中不能出现两个连续的减号,如 i--,会被认作语法错误。
4、Xml数据源请使用utf-8格式,Xsl文件也请使用Utf-8+BOM。编码不一致会产生莫名其妙的错误。

过去5年,我一直使用Xsl模板技术来武装公司的项目,有OA类、电商类等多种类型的项目,实际应用中感觉它还是能经受得起产品经理与客户的折腾,并且还能保持不错的性能。由于弃用aspx页面,因此有好些比较底层的工作需要手动完成,如页面缓存(服务端、浏览器端)、表单安全验证、控件封装等等,好处就是这么走一遭,团队成员整体提升了对HTML/XML的认识,对http协议也有更细致的了解。

 

本系列文章至此终。

 

posted @ 2015-06-10 14:57  蔡大卫  阅读(1916)  评论(1编辑  收藏  举报