zoukankan      html  css  js  c++  java
  • 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协议也有更细致的了解。

    本系列文章至此终。

  • 相关阅读:
    HDU 4801 Pocket Cube
    HDU 5008 Boring String Problem(后缀数组+二分)
    2-Sat问题
    后缀数组
    树形DP
    图论
    SRM 628 DIV2
    组合博弈
    Github使用笔记
    VS2010+OpenCV配置
  • 原文地址:https://www.cnblogs.com/xmlnode/p/4564265.html
Copyright © 2011-2022 走看看