DocBook XSL完全手册(XSL简短介绍)
来源:互联网 发布:爱淘宝和一淘的区别 编辑:程序博客网 时间:2024/06/04 18:46
原文链接:http://www.sagehill.net/docbookxsl/IntroXSL.html
1. XSL处理模型
- 1.1. 重要的上下文环境
- 1.2. 编程特性
- 1.3. 生成HTML
- 1.4. 生成格式化对象(FO)
1. XSL处理模型
XSL是一个模板语言,而不是一个程序语言。这意味着
stylesheet
制 定了一个输出样本,而不是使用程序按步骤生成。一个stylesheet
包 含了一个混合的输出样本,并且为每个样本佩戴了输出指令。每一个晓得输出样本 加上处理指令就构成了一个模板。
通常情况,你要为文档内的每个元素书写一个模板。这样能够让你每次只专注于一个 元素,并持有一个
stylesheet
模块。XSL的强大之 处在于它能够递归的处理模板,也就是说,每个模板只处理它对应的一个元素,然后调 用其它模板来处理它的子元素,以此类推。一个XML文档总是用一个根元素作为顶层 元素,并包含可以嵌套的子元素,XSL模板总是从顶层开始扫描,并照层级来处理元素 。现在用Docbook的
<para>
元 素为例子,要把它转换成HTML,你希望使用HTML标记<p>
来 包围要输出的内容。但是DocBook的<para>
元 素可以包含任何in-line
类型的元素来标记内容;不用担心,你可以让其它对应的模板来处理这些元素,因此你的<para>
XSL模板会是下面这样的 简单: 元素
<xsl:template>
表 示开始一个新的模板,属性match
声明什么元素要 被应用模板,在这个例子中将匹配任何的<para>
元 素。模板指出要输出一个<p>
并 执行<xsl:apply-template>指令。这将告诉XSL处理器在stylesheet
内寻找所有的模板并将其应用到段落中的元素 。如果stylesheet
每个模板都含有一个<xsl:apply-template>
指令,那 么将会递归执行下去。当执行到stylesheet
的末 尾时,模板将输出一个结束的</p>
标 签。 1.1. 重要的 上下文环境
既然不需要用线性的步骤来书写你的文档,那么一个用来描述在什么地方应用这些模 板的“上下文环境”是 尤为重要的。大多数模板都提供了一个
match
属性 来描述上下文环境,这是一个纯粹的表达式语言:XPath,用来标识你文档中的哪个部分将被应用这个模板。简单的上下文环境通常只声明一 个元素名,就像上面的例子。但是你也可以指定元素的子元素,子元素也可以指定属 性值,指定的元素成一个队列的形式,以此类推。下面的模板例子描述如何匹配 DocBook的<formalpara>
元 素 上面定义了三个模板,第一个应用于
<formalpara>
元 素本身,另外两个应用其子元素。在第二个模板中的match
属 性是一个XPath表达式,用来表示这里 的<title>
元素是一个 直接隶属与<formalpara>
元 素的子元素。这就区分与在DocBook中的其它<title>
元 素。XPath表达式是控制模板如何应用 的关键。 通常情况,XSL处理器的内部规则是在面对高层模板和底层模板时,优先应用底层模板 ,这里的层次是元素的层级,文档顶层是高层元素,以此类推。这能够让你更细致的 控制模板应用,但是在你没有为复杂的符合元素提供细致的上下文环境时,XSL处理器 也对其提供了备选方案。这个特性在上面的例子中得以体现,对于
formalpara/para
,例子中提供的第三个模板,<para>
元素作为<formalpara>
元素的子元素,处 理器将使用单独的方式来处理它,它将不会再输出已经被父元素输出的<p>
HTML标签。如果formalpara/para
模板没有包含在上面的例子中,那么处理 器将使用备选的模板match="para"
,这个模板在上 一个例子中定义。这样处理器将输出第二层<p>
HTML 标签。 你也可以使用XSL中的
modes
来控制模板上下文 环境,这种方式已经被广泛应用与DocBook stylesheet中。Modes
能够让你使用不同的方式来处理相同的输入。在<xsl:template>
模板定义中使 用mode
属性将会为模板指定一个mode
命名。这种情况下,当有两个模板指定了相同的mode
属性值,处理器将把math
的 属性值和mode
的属性值通过表达式and连接来作为一个过滤条件,也就是说,当mode
属性值相同时则继续使用match
属 性值匹配来区分使用哪个模板。这就让你对一个元素定义了两个不同的模板来针对 不同的上下文环境。例如,下面对DocBook的<listitem>
元 素定义了两个不同的模板: 第一个模板应用于普通的列表输出情况,模板输出
<li>
HTML 标签来。第二个模板定义为<xsl:apply-templates select="$target" mode="xref"/>
,这种情况下用来专门处理 <xref>
元素。在这个 例子中,mode
属性的值决定应用第二个模板,它将 初始带有序号的列表。因为在输出<xref>
元 素时经常会有这样的需求。 请记住,
mode
的设置不会自动的贯穿处理子模 板<xsl:apply-templates/>
。 当子模板含有mode
属性时,你可以有两个选择来处 理: - 要想继续使用
mode
模式,也就是使用<xsl:apply-templates mode="mode"/>
模 板来处理子元素,处理器将查找具有相同mode
属性 值的模板来应用子元素。注意,这样的话你就没有备选方案,如果模板没有指定mode
属性值,子元素将不会有模板匹配,也就不会被模板 处理。如果你想使用没有mode
属性的模板作为备选 ,那么在stylesheet
中加入下面的模板:这样的话,对于任何子元素,如果模板没有配备mode
属 性值,那么模板也将会被应用 - 使用通常的
无mode
模板,对子元素使用<xsl:apply-templates/>
,你 可以定义无mode
模板
1.2. 编程特性
尽管XSL是模板驱动的,但是它同样具有很多传统编程语言的特性。下面一些例子来 自与DockBook stylesheet
然而你不能像在其它编程语言那样来使用上面这些结构,因为
变量
在特别的情况下会具有完全不同的行为。 1.2.1. 使用 变量和参数
XSL提供两种元素来让你指派值到变量上:
<xsl:variable>
和 <xsl:param>
。它们 享用共同的命名空间和语法,都使用$name
来引用变 量。这两个元素最主要的不同是param's
的默认值 能够被模板调用的<xsl:with-param>
所 取代,就如上面最后一个例子所示。 下面两个例子同样来自DocBook:
在上面两个元素中,
param
和variable
的名字都是通过name
属 性来指定的,可以看到param
的名字是cols
,variable
的名字是 segnum
。它们的值可以通过两种方式来提供,参数 的例子是通过元素的内容值“1”来 赋值的,而变量的例子是通过select
属性值来赋值 的,这个属性值是一个表达式的结果,而元素本身并没有内容值。 对于新接触XSL的用户来说变量的特性有点古怪,当你给一个变量赋值后,你就不能在 它的应用周期内改变它的值,如果这样做会报错。所以你不能像在使用其它编程语 言那样对变量进行动态存储,变量在它的应用周期内持有的是固定值,并在应用周期 结束时销毁。这个特性是在设计XSL时就决定了,因为XSL是模板驱动而非流程驱动的 。这意味着它没有固定的执行顺序,所以你无法依赖一个能够改变值的变量。要想 正确的使用变量,你必须理解变量的周期是如何定义的。
如果一个变量定义在所有模板的外部,那么它就被认为是一个全局变量,它对所有模 板都生效。全局变量的值是固定不变的,也不能被任何模板所重新赋值。但是你可以 在模板内创建一个与全局变量同名的本地变量,然后赋予其它的值。本地变量只能 在其自己的应用周期内起作用。
定义在模板里的本地变量只会在它被允许的周期内生效,也就是对在它之后的同胞和 后裔有效。要想理解这个周期,你必须明白XSL指令其实就是纯粹的XML元素,并内嵌 在XML家族层级结构中。它们通常是指父级、子级、同级、祖先级和后裔级。在 XML家族层级中,给一个变量赋值就像发布一个公告给你希望听到家族成员一样。你 只能把公告发布给比你年龄低的同级(包括你自己)和它们的后裔级,也就是说定义在 你前面的年长的同级将不会听到公告,更不用说你的父级和祖先了。如果你发布不 同的公告内容但是用相同的公告名给相同的被通知成员,那将出现错误,(言外之义,你重新给变量赋值了)。请记住这里的家族并不是你的文档元素,而只是在你
stylesheet
中的XSL指令。手工编写stylesheet
将对你跟踪周期很有帮助,XSL元素缩进和嵌套 将帮助你理解周期。下面的代码片段来自DocBook stylesheet中的pi.xsl
文件,举例说明两个变量周期的不同。 变量
pi
的周期开始于第8行,也就是模板定义 它的位置,结束于第20行它最后一个同级兄弟结束的地方[1]。变量rest
的周 期开始于13行,结束与15行。幸运的是,15行的输出表达式赶在周期结束前使用了变 量值。 让我们来看看当在变量的周期内使用
<xsl:apply-templates/>
会 如何?被应用的模板内会得到变量值吗?答案是否定的。因为被应用的模板生效周期 并没有真正的在变量周期内,它在stylesheet
的其 它地方退出,并不是在变量的低龄同级和后裔内退出。 要想传值给一个模板,你可以使用
<xsl:with-param/>
传 递一个参数。这种参数传递通常被用在使用<xsl:call-templates/>
调 用指定模板,尽管你也可以使用<xsl:apply-templates/>
调 用模板,但是通常被调用的模板希望传入一个与<xsl:param/>
定 义同名的参数。这样就可以在模板内使用这个参数值。任何传入的参数名如果在模 板内没有被定义将被忽略处理。 下面参数传递的例子来自
docbook.xsl
: 上面一个命名为
head.content
的模板被调用 ,在调用周期内传递了一个名为node
的参数,参数值 是变量$doc
。上面被调用的模板看上去会是下面 的样子: 模板期望一个参数是因为模板定义中声明了一个
<xsl:param/>
,并且名字和传入参数名相同。模板内的<xsl:param/>
提 供了一个默认值,如果传入的参数名没有与其匹配,那么将在模板内使用默认值。 1.3. 生成 HTML
从你的DocBook文件生成HTML需要使用HTML版本的
stylesheet
,这些由stylesheet
的HTML驱动文件docbook/html/docbook.xsl
来完成。这是一个主stylesheet
文件,它使用<xsl:include/>
导 入其它组件文件组装一个完整的stylesheet
用来 生成HTML DocBook stylesheet生成HTML的方式是通过应用模板来输出一些文本内容和HTML元素的混合 体。从
docbook.xsl
的顶层开始: 模板匹配到你输入文档的根元素,然后就开始递归应用模板。首先定义了一个变量
doc
,然后输出两个HTML元素<html>
和<head>
。接着调用名为head.content
模板来处理HTML的<head>
,关闭<head>
后就开始<body>
。这里使用<xsl:apply-templates/>
来递 归处理输入文档中的内容,最终关闭像HTML文件的输出。 简单的HTML元素可以用不带任何属性的元素生成,如
<html>
,但是如果HTML元素输出 依赖上下文环境,你就需要一个强大的机制来选取输出元素并且还会生成它们的属 性和属性值。下面的代码片段来自于sections.xsl
,其展示了用<xsl:element>
和 <xsl:attibute>
来生 成HTML的头标签 整个例子生成了一个单独的HTML头元素。第1行定义了一个HTML元素,例子中元素的 名字是一个带有变量
$level
的表达式,变量是通过 参数出入模板的。这样的话模板就会生成<hi>
、 <h2>
、等等。具体生 成哪个依赖于上下文环境。第2行为头元素添加了一个属性class="title"
。第3-5行添加了属性style="clear all"
,但是只适用于头元素的层级数小于3 的情况。第6行打开一个锚元素<a>
。 看上去没带有任何属性,其实是在第7-9行为<a>
元 素添加了name
属性。这个例子描述XSL管理的输出 元素是一个活的元素,而不只是一个文本串。第10行输出头元素的标题文本,同样是 通过传递参数的形式获得,然后关闭HTML粗体标签。第11行使用</a>
关闭锚标签,第12行是头元 素的关闭标签,这就结束了头元素的定义。 当你随着模板的递归来处理元素时,可能会疑惑在你文档里的内容文本是如何被模板 输出的,在
docbook.xsl
文件中你会找到如下的模板,它专门用来内容文本。 这个模板的主体由文本节点的值组成,它只是文本。通常,如果你的
stylesheet
中没有提供匹配的模板,XSL处理器都有一些内 建的模板来获取内容文本。上面的模板就是提供这样的功能,只不过它明确定义在stylesheet
文件中。 1.4. 生成格 式化对象(FO)
使用
fo
版本的stylesheet
可 以把你的DocBook XML生成格式化对象。这里需要在你的stylesheet
中 使用docbook/fo/docbook.xsl
。在你的主stylesheet
文件中使用<xsl:include>
引 入所有的组件组装成完整的stylesheet
来生成格 式化对象。生成格式化对象只完成了输出过程的一半,你还需要使用XSL-FO
处理器,比如FOP。 DocBook的fo stylesheet和HTML stylesheet的工作方式类似,就是用
<fo:something>
形式的标签代 替相应的HTML标签。例如,输出in-line
类型并且使 用monospace
字体,fo的形式会是如下的样子: 输出一个DocBook
<filename>
元 素,在docbook/fo/inline.xsl
中的模板定义看起 来像如下的样子: 在XSL标准中指定了很多XSL-FO标签和属性的规范,要描述在DocBook中如何遵循这些 规范显然已经超出本书的范围。庆幸的是,这些只是中间格式,你不许要马上去处理 ,除非你正在自己编写
stylesheets
。 [1] 从技术上来讲,变量的周期延伸到<xsl:variable>
父 级元素结束的地方,也就是它最后一个同级兄弟
- DocBook XSL完全手册(XSL简短介绍)
- docbook-xsl使用
- XSL
- xsl
- XSL
- XSL
- XSL
- XSL
- xsl
- XSL
- XSL
- xsl
- XSL
- XSL语言(XSL Languages)(1)XSL Languages
- XSL 简 明 教 程(上)
- xsl入门(转)
- xsl学习(转载)
- XSL基础教程(一)
- 【C/C++语言入门篇】-- 调试基础
- Hibernate缓存机制以及一级缓存和二级缓存的作用
- Wince音频驱动的好Blog
- 网站注入与防范ASP.NET
- 禁止root远程直接登录
- DocBook XSL完全手册(XSL简短介绍)
- Android 支持的文件类型
- Response.Redirect,Server.Execute和Server.Transfer的区别
- 悬而未决:如何动态统计连接到本机某一端口的同一IP的连接数量
- 【C/C++语言入门篇】-- 深入指针
- 关于项目进度慢的思考----如何提高整体开发效率
- 伪实现停靠窗口?很拙略的办法,勉强实现!
- java正规表达式相关问题
- 在 vs 中 调试 lua脚本