基础篇: XSLT快速参考
2007-03-12 13:22
399 查看
1 前言
在第1章中,我们用一个简单的XSLT样式表作为例子介绍了XSLT的概要。当然,XSLT所拥有的元素并不仅限于xsl:template、xsl:apply-templates、xsl:value-of。为了实行转换,XSLT准备了各种各样的元素。本章将以最常用的元素为中心举例说明。另外,本文中并不准备介绍元素的全部属性。详情请参见W3C标准的原文[1]及译文[2]等。
在XSLT中经常会用到一种被称为XPath的描述方法。首先从XPath的概要开始介绍。
2 XPath是什么?
XPath是树结构的一种描述方法。在创建XSL样式表时经常使用XPath。2.1 树结构
XML文档表示的数据组成数结构。用XLST进行转换,也就是从源文档的树(源树)生成转换后的树(目标树)的意思。这个转换以树结构的节点为基础来进行。节点有几种,主要为:
表示根的“根节点”
表示元素的“元素节点”
表示属性的“属性节点”
表示文本的“文本节点”
表示注释的“注释节点”
使用像这样的各种各样的节点来表示树的位置的描述方法称为XPath。
2.2 XPath表达式
创建XSLT样式表时经常使用的XPath表达式如表1所示。所谓的上下文节点,就是由上下文构成的节点,可以理解为“处理对象”。另外,今后会出现“当前节点”的概念,可以理解为“被选中的节点”。 1描述类似于UNIX的路径描述。例如,
[code]<html> <body> <a href="sample.html">示例</a> <ul> <li>项目A</li> <li>项目B</li> </ul> </body></html>
[/code]
中,表示元素a的XPath表达式为
/html/body/a
此外,若表示a元素的href属性,则为
/html/body/a/@href
表中a[表达式]是符合表达式的a项目的意思,例如表示第一个li项目时使用
/html/body/ul/li[1]
3 定义样式表的元素
XSLT样式表使用XML文档的格式创建。因此,必须要遵从XML文档的描述规则。XML文档中必须存在的元素只有根元素。在XSLT样式表中的根元素就是xsl:stylesheet元素。基本代码如下所示:[code]<xsl:stylesheet version = "版本号"> <!-- 内容: (xsl:import*, 顶层元素) --></xsl:stylesheet>
[/code]
4 模板规则
XSLT样式表可以说是模板规则的集合。4.1 模板规则的定义
模板规则使用xsl:template元素进行定义。它的属性包括match、name、priority和mode。其中最重要的是match属性,该属性规定了节点的样式。若没有指定name属性的话,就必须指定match属性。基本的代码如下所示。[code]<xsl:template match = "样式" name = "名称"> <!-- 内容: (xsl:param*, 模板) --></xsl:template>
[/code]
name属性将在调用命名模板时使用。关于命名模版将在后面讲述。
4.2 应用模板规则
我们使用xsl:apply-template元素来应用模板规则。它包含select和mode属性。基本的代码如下所示:[code]<xsl:apply-templates select = "节点集合表达式"> <!-- 内容: (xsl:sort | xsl:with-param)* --></xsl:apply-templates>
[/code]
后面将讲到的排序操作等之外的情况下该元素不需要内容,因此空元素标记可以写成以下的形式:
[code]<xsl:apply-templates select="节点集合表达式"/>
[/code]
未指定select属性时,当前节点为所有的子节点。
通常,仅在处理当前节点的子孙节点时使用该元素。这样就不会发生无法终了的无限循环。不能定义如下例所示的无限循环模版:
[code]<xsl:template match="x"> <xsl:apply-templates select="."/></xsl:template>
[/code]
4.3 命名模版
带有name属性的模板规则可以通过模版名称来调用。[code]<xsl:call-template name = "名称"> <!-- 内容: xsl:with-param* --></xsl:call-template>
[/code]
例如,定义下例所示的模板规则时,
[code]<xsl:template name="hello"> 你好</xsl:template>
[/code]
可以以下面的方式调用:
[code]<xsl:call-template name="hello"/>
[/code]
输出为:
[code]你好
[/code]
4.4 匹配冲突
某个指定的表达式可能会出现多个匹配结果。这时根据优先度来决定应用哪个模板。定义模板规则时可通过设置priority属性来显式地指定模板优先度。如未指定,将采用默认优先度。关于默认优先度的计算方法请参见参考文献[1]。一般来说限制性强的表达式优先度较高。例如“a”的优先度要高于“*”。4.5 内嵌模版规则
内嵌模板规则即为默认模板规则,不匹配任何模板规则的节点将由它来处理。这种机制保证了即使在不定义任何模板规则的情况下,模版处理也能递归地进行下去。应用于元素节点和根节点的内嵌模板规则如下所示。
[code]<xsl:template match="*|/"> <xsl:apply-templates/></xsl:template>
[/code]
应用于文本节点和属性节点的内嵌模板规则如下所示。
[code]<xsl:template match="text()|@*"> <xsl:value-of select="."/></xsl:template>
[/code]
对于其他节点(如注释节点等)不做任何处理。
这种模板规则将把文本节点内容全部输出。将代码1所示的XSLT样式表应用到某个XML文档上之后,将生成以doc为根节点、文本节点为内容的XML文档。
代码1: builtin.xsl
[code]<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <doc> <xsl:apply-templates/> </doc> </xsl:template></xsl:stylesheet>
[/code]
5 输出
虽然称为“输出”,但实际的意思是“生成目标树的节点”。可以使用源树生成节点,也可以直接生成节点。5.1 取出文本
xsl:value-of元素可以将指定的节点的值作为字符串来输出。必须要指定select属性。[code]<xsl:value-of select = "字符串表达式"/>
[/code]
指定的树种包含其它元素时,文本节点以外的节点将被忽略,仅输出文本。例如,
[code]<p>.com时代的<b>IT</b>杂志</p>
[/code]
对该树应用
[code]<xsl:value-of select="p"/>
[/code]
时,输出为
[code].com时代的IT杂志
[/code]
选择当前节点可以使用“.”。若将
[code]<a href="http://www.gihyo.co.jp"> 技术评论公司</a>
[/code]
作为当前节点,那么
[code]<xsl:value-of select="."/>的URL是<xsl:value-of select="@href"/>。
[/code]
的输出为
[code]技术评论公司的URL是http://www.gihyo.co.jp。
[/code]
5.2 节点复制
xsl:value-of元素将节点的值转换为字符串。与此相对,xsl:copy-of元素将复制节点,节点中包含的子元素原封不动。基本的代码如下所示。[code]<xsl:copy-of select = "表达式"/>
[/code]
例如、
[code]<p>.com时代的<b>IT</b>杂志</p>
[/code]
对此应用
[code]<xsl:copy-of select="p"/>
[/code]
的话,输出为
[code]<p>.com时代的<b>IT</b>杂志</p>
[/code]
5.3 属性值模板
需要生成属性值时,可以使用大括号{}将表达式括起来。。2例如,想由
[code]<link> <title>技术评论公司</title> <url>http://www.gihyo.co.jp/</url></link>
[/code]
生成如下的HTML链接时,
[code]<a href="http://www.gihyo.co.jp/"> 技术评论公司</a>
[/code]
可以定义如下的模板规则。
[code]<xsl:template match="link"> <a href="{url}"> <xsl:value-of select="title"/> </a></xsl:template>
[/code]
5.4 生成文本
xsl:text元素可以生成文本节点。由于生成文本时直接将文本写出即可,所以一般情况下该元素不使用。但是若需要令输出的转义字符失效的话就需要使用该元素。基本代码如下所示。[code]<xsl:text disable-output-escaping = "yes" | "no"> <!-- 内容: #PCDATA --></xsl:text>
[/code]
通过disable-output-escaping属性可以指定输出转义字符是否无效。默认值是no。指定为on时,
[code]<xsl:text disable-output-escaping="yes"> <</xsl:text>
[/code]
的输出为
[code] <
[/code]
5.5 生成注释
需要生成注释时可以使用xsl:comment元素。[code]<xsl:commwnt>这里是注释。</xsl:comment>
[/code]
的输出如下所示。
[code]<!--这里是注释。-->
[/code]
5.6 复制
复制当前节点可以使用xsl:copy元素。属性和子节点不会被自动复制。基本代码如下所示。[code]<xsl:copy> <!-- 内容:模板 --></xsl:copy>
[/code]
例如,将没有属性的上下文元素属性原样输出,可以使用如下的模板规则。
[code]<xsl:template match="content"> <xsl:copy> <xsl:value-of select="."/> </xsl:copy></xsl:template>
[/code]
若需要递归地复制所有节点,可以使用如下的模板规则。
[code]<xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy></xsl:template>
[/code]
5.7 生成元素
需要生成元素时可以使用xsl:element元素。通常,只要将需要生成的元素直接写出即可,不必使用xsl:element元素。该元素仅在需要动态生成元素时才有必要使用。基本代码如下所示。[code]<xsl:element name = "生成元素的名称"> <!-- 内容: 模板 --></xsl:element>
[/code]
例如,若要由
[code]<heading> <text>这是标题。</text> <size>2</size></heading>
[/code]
生成HTML标题(h元素),则可以使用如下的模板规则。
[code]<xsl:template match="heading"> <xsl:element name="{concat('h', size)}"> <xsl:value-of select="text"/> </xsl:element></xsl:template>
[/code]
concat()是字符串连接函数。从size元素中取出值并将其连接在“h”之后构成元素名。输出如下所示。
[code]<h2>这是标题。</h2>
[/code]
5.8 生成属性
需要生成属性时可以使用xsl:attribute元素。与生成元素的情况相同,通常只需要将需要生成的属性直接写出即可,不需使用xsl:attribute元素。该元素仅在需要动态生成属性等场合才有必要使用。基本代码如下所示。[code]<xsl:attribute name = "生成属性的名称"> <!-- 内容:模板 --></xsl:attribute>
[/code]
例如 ,若想由 3
[code]<link> <title>技术评论公司</title> <url>http://www.gihyo.co.jp/</url></link>
[/code]
生成如下的HTML链接时,
[code]<a href="http://www.gihyo.co.jp/"> 技術評論社</a>
[/code]
可以定义如下的模板规则。
[code]<xsl:template match="link"> <a> <xsl:attribute name="href"> <xsl:value-of select="url"/> </xsl:attribute> <xsl:value-of select="title"/> </a> </xsl:template>
[/code]
5.9 添加编号
需要输出整数值时可以使用xsl:number元素。基本代码如下所示。[code]<xsl:number level = "源树的级别" count = "表达式" from = "表达式" value = "数值表达式" format = "表示格式的字符串" />
[/code]
首先看看最简单的例子。
[code]<items> <item>A</item> <item>D</item> <item>B</item> <item>C</item></items>
[/code]
对该XML文档定义如下的模板规则。
[code]<xsl:template match="items"> <xsl:copy> <xsl:apply-templates select="item"/> </xsl:copy></xsl:template><xsl:template match="item"> <xsl:copy> <xsl:number/> <xsl:text> </xsl:text> <xsl:value-of select="."/> </xsl:copy></xsl:template>
[/code]
生成结果如下所示。
[code]<items> <item>1 A</item> <item>2 D</item> <item>3 B</item> <item>4 C</item></items>
[/code]
省略value属性时,则根据源树内当前节点的位置来输出数值。由于这个原因,若使用后面将要讲到的排序元素的话,即如果定义如下所示的模板规则的话,
[code]<xsl:template match="items"> <xsl:copy> <xsl:for-each select="item"> <xsl:sort select="."/> <xsl:copy> <xsl:number/> <xsl:text> </xsl:text> <xsl:value-of select="."/> </xsl:copy> </xsl:for-each> </xsl:copy></xsl:template>
[/code]
输出结果将如下所示。
[code]<items> <item>1 A</item> <item>3 B</item> <item>4 C</item> <item>2 D</item></items>
[/code]
需要按照排序结果的顺序来添加编号的话,则须按照如下方式指定value属性。position()函数返回正在处理的上下文节点的位置。
[code]<xsl:number value="position()"/>
[/code]
可以使用level属性、count属性、from属性来控制编号方法。count属性设置应当被编号的节点。level属性设置作为编号对象的源树的级别。可指定的级别有single、multiple、any三种,默认值为single。
例如,有下面这种层次结构的XML文档。
[code]<chapter title="第一章"> <section title="第一节"> <subsection title="第一部分"> </subsection> </section> <section title="第二节"> <subsection title="第二部分"> </subsection> <subsection title="第三部分"> </subsection> </section></chapter>
[/code]
将xsl:number元素的level属性设置为single,即将如下的模板规则应用于该文档,
[code]<xsl:template match="chapter|section|subsection"> <xsl:apply-templates select="@title"/> <xsl:apply-templates select="*"/></xsl:template><xsl:template match="@title"> <xsl:number level="single" count="chapter|section|subsection"/> <xsl:text> </xsl:text> <xsl:value-of select="."/><br/></xsl:template>
[/code]
转换结果如下所示。
[code]1 第一章<br/>1 第一节<br/>1 第一部分<br/>2 第二节<br/>1 第二部分<br/>2 第三部分<br/>
[/code]
也就是输出在兄弟节点中当前节点的位置。设置level属性为multiple时,转换结果如下所示。
[code]1 第一章<br/>1.1 第一节<br/>1.1.1 第一部分<br/>1.2 第二节<br/>1.2.1 第二部分<br/>1.2.2 第三部分<br/>
[/code]
编号与single相同,但是增加了父节点的编号。设置level属性为any时,转换结果如下所示。
[code]1 第一章<br/>2 第一节<br/>3 第一部分<br/>4 第二节<br/>5 第二部分<br/>6 第三部分<br/>
[/code]
也就是按照符合count指定的表达式的节点的顺序输出序号。
from属性设置计数开始的位置。例如,考虑如下的XML文档。从逻辑上看,各个节点之间有父子关系,但是在源树中各个节点是并列关系。
[code]<h1>大标题一</h1><h2>中标题一</h2><h3>小标题一</h3><h2>中标题二</h2><h3>小标题二</h3><h3>小标题三</h3>
[/code]
下面使用from属性设置计数开始的节点。
[code]<xsl:template match="h1"> <xsl:number/> <xsl:text> </xsl:text> <xsl:value-of select="."/><br/></xsl:template><xsl:template match="h2"> <xsl:number level="any" count="h1"/> <xsl:text>.</xsl:text> <xsl:number level="any" from="h1" count="h2"/> <xsl:text> </xsl:text> <xsl:value-of select="."/><br/></xsl:template><xsl:template match="h3"> <xsl:number level="any" count="h1"/> <xsl:text>.</xsl:text> <xsl:number level="any" from="h1" count="h2"/> <xsl:text>.</xsl:text> <xsl:number level="any" from="h2" count="h3"/> <xsl:text> </xsl:text> <xsl:value-of select="."/><br/></xsl:template>
[/code]
转换结果如下所示。
[code]1 大标题一<br/>1.1 中标题一<br/>1.1.1 小标题一<br/>1.2 中标题二<br/>1.2.1 小标题二<br/>1.2.2 小标题三<br/>
[/code]
使用format属性设置输出文字的格式。默认的格式为“1”,即输出数字。用于表示格式的字符串如表2所示。
[align=left]我们上面的例子中为了在xsl:number元素之后加一个空格,不得不使用了xsl:text元素。实际上只要将format属性设置为“1 ”就可以了。level属性为multiple的情况下也可以指定类似于“1.A.I”这样的格式。[/align]
相关文章推荐
- XSLT入门 -- 第2章 基础篇: XSLT快速参考1 [转]
- XSLT入门 -- 第2章 基础篇: XSLT快速参考1 [转]
- XSLT入门 -- 第2章 基础篇: XSLT快速参考2 [转]
- XSLT快速参考
- XSLT快速参考
- XSLT快速参考
- XSLT快速参考
- 假导出Excel功能实现,按CSV格式快速导出功能代码参考(追求代码追求简洁复用)浙江杭州
- 嵌入式Linux图形系统(GUI)快速参考手册
- SED单行脚本快速参考
- awk单行脚本快速参考
- Objective-C语法快速参考
- BEA WEBLOGIC 集群快速安装参考
- Objective-C语法快速参考
- 3. GC 算法(基础篇) - GC参考手册
- SQL 快速参考
- 注重实效的程序员之快速参考指南
- Objective-C语法快速参考
- 5. GC 调优(基础篇) - GC参考手册
- ASP.NET MVC快速开发框架清新简洁界面设计,有兴趣可以模仿参考