到目前为止,我已经含蓄地假定数值是以1、2、3等等表示的;也就是说,用的是以1开始的,并且间隔数为1的欧洲数字。但并非只有这种情况。例如,书的前言以及前面其他内容的页号通常是以小写罗马数字(如i、ii、iii、iv等等)表示的。并且,不同的国家将数字组合在一起、将实数的整数和小数分开以及使用符号来表示各种数字的习惯不同。所有的这一切都可以通过下面xsl:number的五个特性来调整:
* format
* letter-value
* digit-group-sep
* n-digits-per-group
* sequence-src
14.11.2.1 format特性
使用format特性,可调整xsl:number使用的编号样式。此特性通常可使用下列值之一:
* i:生成小写的罗马数字i、ii、iii、iv、v、vi、1/4 表示的序列
* I:生成大写的罗马数字I、II、III、IV、V、VI、1/4 表示的序列
* a:生成小写的字母a、b、c、d、e、f、1/4 表示的序列
* A:生成大写字母A、B、C、D、E、F、1/4 表示的序列
例如,下面的规则使用大写罗马数字对原子进行编号:
<xsl:template match="ATOM">
<P>
<xsl:number expr="position()" format="I"/>
<xsl:value-of select="."/>
</P>
</xsl:template>
改变format特性的值,可调整在哪个数字(或字母)处开始计数。例如,要在5处开始编号,可设置format="5"。要以iii开始编写,可设置format="iii"。
使在format特性中数字的第一位数为0,即可指定以0开始的十位数编号方式。例如,设置format="01",可生成序列号为01、02、03、04、05、06、07、08、09、10、11、12、1/4 。这里将数字排成一列是很有用的。
14.11.2.2 letter-value特性
letter-value特性区别是将字母翻译为数字还是翻译为字母。例如,如果要想使用format="I",获得一个I、J、K、L、M、N、...序列,而不是I、II、III、IV、V、VI、...序列,则应将letter-value特性设置为关键字alphabetic。关键字other指定数字序列。例如
<xsl:template match="ATOM">
<P>
<xsl:number expr="position()"
format="I" letter-value="alphabetic"/>
<xsl:value-of select="."/>
</P>
</xsl:template>
14.11.2.3 Group Separator特性
在美国,我们倾向于使用逗号将每三个数字作为一组,来写出大数字,如4,567,302,000。但是,在许多语言和国家里,而是使用句号或空格来分隔各组;例如,4.567.302.000或4 567 302 000。而且,在有些国家,习惯将大数字分成每四个一组,而不是三个一组;例如4,5673,0000。如果处理可能包括几千或更多项的很长序列时,就需要考虑这些问题。
digit-group-sep特性指定用于数字组之间的分组分隔符。n-digits-per-group特性指定每组中使用的数字个数。一般来说,应将这些特性随语言一起指定。例如:
<xsl:number digit-group-sep=" "/>
14.11.2.4 sequence-src特性
最后一点,如果要使用非正常的序列(像1-1-1999、1-2-1999、1-3-1999、...日期字符串列表,或者像10、20、30、40、...间隔为10的列表),可以将此列表(以崭穹挚┍4嬖诙懒⒌奈牡抵小equence-src特性的值表示该文档的相对或绝对的URL。例如:
<xsl:number sequence-src="1999.txt"/>
14.12 对输出元素排序
xsl:sort元素将输出元素按不同于输入文档中的顺序进行排序。xsl:sort元素作为xsl:apply-templates或xsl:for-each的子元素出现。Xsl:sort元素的select特性定义关键字,用来按照xsl:apply-templates或xsl:for-each对元素的输出进行排序。
在缺省情况下,以关键值的字母顺序进行排序。如果在给定的xsl:apply-templates或xsl:for-each元素中,存在一个以上的xsl:sort元素,那么输出内容首先按第一个关键字进行排序,然后按第二个关键字进行排序,依次类推。如果任何元素的比较结果是一样的,那么就按源文档的顺序输出。
例如,假设在一文件中,全部都是以字母顺序排列的ATOM元素。为了要按原子序数进行排序,可使用**14-18中的样式单。
**14-18:按原子序数排序的XSL样式单
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
<xsl:template match="PERIODIC_TABLE">
<html>
<head>
<title>Atomic Number vs. Atomic Weight</title>
</head>
<body>
<hl>Atomic Number vs. Atomic Weight</hl>
<table>
<th>Element</th>
<th>Atomic Number</th>
<th>Atomic Weight</th>
<xsl:apply-templates>
<xsl:sort select="ATOMIC_NUMBER"/>
</xsl:apply-templates>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="ATOM">
<tr>
<td><xsl:apply-templates select="NAME"/></td>
<td><xsl:apply-templates select="ATOMIC_NUMBER"/></td>
<td><xsl:apply-templates select="ATOMIC_WEIGHT"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
图14-5显示的结果表明了以字母顺序排序的局限。原子序数为1的氢是第一个元素。但是第二个元素不是原子序数为2的氦,而是原子数为10的氖。尽管按数字10排在9之后,但按照字母,10却在2之前。
图14-5 按原子序数的字母顺序排序的原子
但是,通过指导可选的data-type特性设置为number,即可调整排列顺序。例如,
<xsl:sort data-type="number" select="ATOMIC_NUMBER"/>
图14-6显示了正确排序的元素。
图14-6 以数字顺序对原子序数进行排序的原子
按照下面的方法,将order特性设置为descending,即可使排列顺序从缺省的升序改为降序:
<xsl:sort order="descending"
sort="number"
select="ATOMIC_NUMBER"/>
这样就使元素从最大到最小的原子序数进行排列,所以氢现在处于表的最后。
以字母顺序进行的排序自然依赖于字母表。lang特性可设置关键字的语言。此特性的值应是一种ISO 639语言码,如对于英语为en。
这些值与xml:lang特性支持的值相同,这在第10章"DTD中特性声明"中已经讨论过。
最后,可将case-order特性设置为upper-first或lower-first两个值当中的一个,以指定大写字母是排在小写字母之前,还是反过来。缺省状况依赖于语言。
14.13 CDATA和<符
标准的XSL无法在输出文档中插入原始的、未转义的不是标记一部分的 < 符号。原始的小于号使输出文档结构混乱,这是XSL不允许的。作为一种替代方法,如果使用如<的字符引用或实体引用<来插入<符号,格式化程序将插入<或可能为<。
当将JavaScript嵌入到页面中时,由于JavaScript使用 < 符号表示数字的小于,而不是表示标记的开始处,这时,这种问题就变得重要。
但是,还是可在输出文档中插入原始的、未转义的 > 和 >= 符号的。因此,如果输出文档需要包含数字比较关系的JavaScript,那么可颠倒操作数的顺序,将小于比较关系重写成大于等于比较关系。同样,可将小于等于比较关系重写成大于比较关系。例如,下面为几行JavaScript代码,在我的很多Web网页中使用了这些代码:
if (location.host.tolowercase().indexof("sunsite") < 0) {
location.target="_blank" href="http://www.cncfan.com/outurl.asp?url=http://metalab.unc.edu/xml/";
}
由于在前两行中使用了小于号,致使这些行结构混乱。但这些语句与下面的这些语句是完全等效的:
if (0 > location.host.tolowercase().indexof("sunsite")) {
location.target="_blank" href="http://www.cncfan.com/outurl.asp?url=http://metalab.unc.edu/xml/";
}
如果将布尔操作符组合起来进行多重测试,那么可能需要将逻辑“和”改为逻辑“或”。例如,下面两行JavaScript非常有效地用来测试页面的位置既不在metalab处,也不在sunsite处:
if (location.host.toLowerCase().indexOf("metalab") < 0
&& location.host.tolowercase().indexof("sunsite") < 0) {
location.target="_blank" href="http://www.cncfan.com/outurl.asp?url=http://metalab.unc.edu/xml/";
}
由于在前两行中使用了小于号,致使这些语句结构混乱。但下面的这些行也是用来测试页面是在metalab上还是在sunsite上,与上面的代码行是完全等效的:
if (0 > location.host.toLowerCase().indexOf("metalab")
|| 0 > location.host.tolowercase().indexof("sunsite")) {
location.target="_blank" href="http://www.cncfan.com/outurl.asp?url=http://metalab.unc.edu/xml/";
}
也可以将这种令人不快的JavaScript放在独立的文档中,并从SCRIPT元素的SRC特性中与之进行链接。但是,这在Internet Explorer 4和Netscape Navigator 3之前的版本中是不可靠的。
出于简化的目的,在输出文档中CDATA部分是不允许的。CDATA部分总是可以用带有Unicode转义(escape)的等价字符集合来代替出问题的 < 号和 & 号。CDATA完全是为人类手工编写XML文件提供的便利。计算机程序,如XSL格式化程序并不需要CDATA部分。
为向输出文档中插入CDATA部分,包括在Internet Explorer 5.0中的XSL格式化程序的确支持非标准的xsl:cdata元素。但是,这一特点未必会加入到标准的XSL中,甚至会从将来的Internet Explorer版本中将此功能删除。
14.14 方式
有时,要在输出文档中多次地包括源文档中的相同内容。要达到此目的是很容易的:只需多次地应用模板,在每个要使数据出现的地方应用一次。但是,假如要在不同的地方对数据进行不同的格式化,那怎么办呢?这是个比较棘手的问题。
例如,若要使处理周期表的输出文档形成与100个更详细描述各原子信息的链接。在此情况下,输出文档的开始很可能如下:
<UL>
<LI><A HREF="#Ac">Actinium</A></LI>
<LI><A HRFF="#Al">Aluminum</A></LI>
<LI><A HREF="#Am">Americium</A></LI>
<LI><A HREF="#Sb">Antimony</A></LI>
<LI><A HREF="#Ar">Argon</A></LI>
?
在文档的后面,出现真正的原子的描述,格式化后与下面的类似:
<H3><A NAME="Al">Aluminum</A></H3><P>
Aluminum
26.98154
13
3
2740
933.5
Al
2.7
</P>
无论何时自动生成超文本的目录或索引,使用这类方法都是很普遍的。原子的NAME在目录中必须格式化成与文档主体中不同的格式。为此,需要在文档的不同地方将两个不同的规则应用于ATOM元素。此解决办法是把每个不同的规则给予mode特性。然后设置xsl-apply-templates元素的mode特性来选择准备应用的模板。
**14-19:在两个不同地方使用mode来对相同数据进行不同的格式化的XSL样式单
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
<xsl:template match="/PERIODIC_TABLE">
<HTML>
<HEAD><TITLE>The Elements</TITLE></HEAD>
<BODY>
<H2>Table of Contents</H2>
<UL>
<xsl:apply-templates select="ATOM" mode="toc"/>
</UL>
<H2>The Elements</H2>
<xsl:apply-templates select="ATOM" mode="full"/>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="ATOM" mode="toc">
<LI><A>
<xsl:attribute name="HREF">#(xsl:value-of
select="SYMBOL"/></xsl:attribute>
<xsl:value-of select="NAME"/>
</A></LI>
</xsl:template>
<xsl:template match="ATOM" mode="full">
<H3><A>
<xsl:attribute name="NAME">
<xsl:value-of select="SYMBOL"/>
</xsl:attribute>
<xsl:value-of select="NAME"/>
</A></H3>
<P>
<xsl:value-of select="."/>
</P>
</xsl:template>
</xsl:stylesheet>
14.15 使用xsl:variable定义常数
命名的常数有助于代码的整洁;可以用简单的名称和引用来代替常用的样板文本;简单地改变常数定义,就能很容易地调整多处出现的样板文本。
xsl:variable元素定义命名的字符串,以便借助于特性值模板用于样式单中的其他地方。xsl:variable是一空元素,是xsl:stylesheet的直系子元素。它只有唯一的一个特性name,此特性提供引用变量的名称。xsl:variable元素的内容作为替换文本。例如,下面的xsl:variable元素定义名为copy99和值为Copyright 1999 Elliotte Rusty Harold的变量:
<xsl:variable name="copy99">
Copyright 1999 Elliotte Rusty Harold
</xsl:variable>
为了访问此变量的值,可将美元符作为前缀加到此变量名前。要在特性中插入此符号,可使用特性值模板。例如:
<BLOCK COPYRIGHT="{$copy99}">
</BLOCK >
还可以使用xsl:value-of,将变量的替换文本以文本的形式插入到输出文档中:
<xsl:value-of select="$copy99"/>
xsl:variable的内容可以含有包括其他XSL指令的标记。这意味着可根据其他信息(包括其他变量的值)来计算变量的值。但是,变量不能以直接或间接的方式递归地引用其自身。例如,下面的例子是错误的:
<xsl:variable name="GNU">
<xsl:value-of select="$GNU"/> s not Unix
</xsl:variable>
同样,两个变量不能像下面这样循环地相互引用:
<xsl:variable name="Thingl">
Thingl loves <xsl:value-of select="$Thing2"/>
</xsl:variable>
<xsl:variable name="Thing2">
Thing2 loves <xsl:value-of select="$Thingl"/>
</xsl:variable>
14.16 命名模板
变量只限于基本的文本和标记。XSL提供了功能更强大的宏工具,可以封装标准的标记和改变数据的文本。例如,假定要将原子的原子序数、原子量和其他关键值分别作为表的单元格,以小型的、粗体的蓝色Times字体来格式化。换句话说,要获得类似于下面的输入结果:
<td>
<font face="Times, serif" color="blue" size="2">
<b>52</b>
</font>
</td>
当然,还可以在模板规则中包含类似于下面的所有内容:
<xsl:template match="ATOMIC_NUMBER">
<td>
<font face="Times, serif" color="blue" size="2">
<b>
<xsl:value-of select="."/>
</b>
</font>
</td>
</xsl:template>
这些标记可作为其他模板,或作为其他规则中使用的模板的一部分而重复使用。当详细的标记变得更为复杂时,当标记出现于样式单中的几个不同地方时,可将它转换成命名的模板。命名的模板与变量类似,但能够包括从应用模板的位置获得的数据,而不是仅仅插入固定的文本。
xsl:template元素有name特性,使用此特性,可隐性地调用该元素,甚至在非间接地应用此元素时也是如此。例如,下面显示的是用于给上面模式命名的模板:
<xsl:template name="ATOM_CELL">
<td>
<font face="Times, serif" color="blue" size="2">
<b>
<xsl:value-of select="."/>
</b>
</font>
</td>
</xsl:template>
宏中间的<xsl:value-of select="."/>元素被替换为调用此模板的当前节点的内容。
xsl:call-template元素出现在模板规则的内容中,必须有name参数,用来对此元素要调用的模板进行命名。处理后,xsl:call-template元素被它命名的xsl:call-template元素的内容所代替。例如,现在我们使用xsl:cal-template元素来调用给模板命名的ATOM_CELL,那么可按下列方法重写ATOMIC_NUMBER规则:
<xsl:template match="ATOMIC_NUMBER">
<xsl:call-template name="ATOM_CELL"/>
</xsl:template>
这种相当简单的例子仅省掉了几行代码,但模板越复杂,并且重复使用的次数越多,样式单的复杂程度降低得就越大。命名的模板正如变量一样,还有提取样式单中的通用模式的优点,所以可作为一个模板来编辑。例如,如果要将原子序数、原子量和其他关键值的颜色由蓝色改变为红色,那么只需要在命名模板中对此改变一次即可。不必在每个分立的模板规则中单独改变此颜色。这有助于在较长的开发过程中,使样式保持更大的一致性。
14.16.1 参数
对命名模板的每一次分开调用,都可将参数传递给模板,以便定制其输出内容。在xsl:template元素中,参数是由xsl:param-variable子元素来表示的。在xsl:call-template元素中,参数是由xsl:param子元素来表示的。
例如,假定要将每个原子单元格链接到一特定的文件中。其输出类似于下列情景:
<td>
<font face="Times, serif" color="blue" size="2">
<b>
<a href="atomic_number.html">52</a>
</b>
</font>
</td>
其诀窍是,由于对模板的每次分开调用都会引起href特性的值发生变化,所以必须从调用模板的位置将href特性的值传递过去。
<td>
<font face="Times, serif" color="blue" size="2">
<b>
<a href="atomic_weight.html">4.0026</a>
</b>
</font>
</td>
支持此种情况的模板与下列代码类似:
<xsl:template name="ATOM_CELL">
<xsl:param-variable name="file">
index.html
</xsl:param-variable>
<td>
<font face="Times, serif" color="blue" size="2">
<b>
<a href="{$file}"><xsl:value-of select="."/></a>
</b>
</font>
</td>
</xsl:template>
xsl:param-variable元素的name特性给参数起个名称(如果有多个参数则更为重要),如果调用过程不提供值的话,那么xsl:param-variable元素的内容就为要使用的这个参数提供一个缺省值。(这个缺省值还可以使用expr特性,以字符串表达式的形式给出,与xsl:variable完全一样。)
当调用此模板时,xsl:call-template元素的xsl:param子元素使用其name特性来识别参数、使用其内容来给参数提供一个值的方法,从而提供该参数的值。例如:
<xsl:template match="ATOMIC_NUMBER">
<xsl:call template macro="ATOM_CELL">
<xsl:param name="file">atomic_number.html</xsl:param>
<xsl:value-of select="."/>
</xsl:call-template>
</xsl:template>
这是一个相当简单的例子,但复杂得多的命名模板是存在的。例如,为了用于许多不同样式单(每种样式单一定要单独改变网页作者名字、网页标题和版权日期几个参数)的输入,很可能需要定义Web站点上网页的页眉和页脚宏。
14.17 删除和保留空白
读者可能已经注意到,到目前为止,所有输出实例的格式化方式都有点奇怪。造成这种现象的原因是,源文档需要将长行划分成多行,以便适合本书页边距的要求。不幸的是,往输入文档中增加额外的空白,就会带到输出文档中。对于计算机来说,毫无意义的空白的具体内容并不重要,但对于人来说,这些空白内容就令人困惑。
像ATOMIC_NUMBER或DENSITY元素那样,用于文本节点的缺省行为就是保留所有的空白。常见的DENSITY元素看起来如下面那样:
<DENSITY UNITS="grams/cubic centimeter"><!- At 300K ->
7.9
</DENSITY>
当取其值时,值中就会包括首、尾空白(如下所示),尽管这个空白在此处只是用来满足打印页面的要求,但没有什么实际意义:
7.9
但是,有一种例外的情况。如果文本节点只含有空白,没有其他文本,那么这个空白就认为是毫无意义,并被删除。但对此例外还有一种例外:如果文本先辈的xml:space特性保存有值,那么就不会删除此文本,除非更近的先辈的xml:space特性具有缺省值。(这种情况听起来有点复杂,但实际上很简单。所有的一切都说明,可忽略只含有空白的文本节点,除非这些文本节点明确地设置成有意义的空白。对于其他情况,空白被保留。)
如果文档中的任何元素都不保留空白,那么可设置xsl:stylesheet元素的default-space特性为strip,所有的首尾空白在从文本的节点中删除之后,才输出这些节点文本。对于周期表来说,这最容易实现。例如:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
default-space="strip">
如果想保留所有元素中的空白,可使用xsl:strip-space元素,用它识别输入文档中指定的元素,如果指定的元素表明文档中的空白毫无意义,就不将此空白复制到输出文档中。element特性识别要截去过剩空白的元素。例如,下面的这些规则加到周期表样式单中,可避免过多的空白:
<xsl:strip-space element="DENSITY"/>
<xsl:strip-space element="BOILING_POINT"/>
<xsl:strip-space element="MELTING_POINT"/>
xsl:preserve-space元素与xsl:strip-space元素相反。其element特性命名的元素表示其空白应保留。例如:
<xsl:preserve-space element="ATOM"/>
样式单内部的空白(正好与输出XML文档中的空白相反)是毫无意义的,在缺省情况下简化为一个空格。这种情况是可以避免的:只需将文字空白放在xsl:text元素之间。例如:
<xsl:template select="ATOM">
<xsl:text> This is indented exactly five spaces. </xsl:text>
</xsl:template>
处理空白的一个一劳永逸的方法就是将indent-result特性与根xsl:stylesheet元素相关联。如果此特性的值为yes,那么就允许处理程序将多余的空白插入到(而不是删除)输出文档中,以便使输出文档看起来好看一些。这包括缩排和行分隔符。例如:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=
http://www.w3.org/XSL/Transform/1.0indent result="yes">
<!- usual templates and such go here... ->
</xsl:stylesheet>
如果生成的是HTML,指定indent-result="yes"就可使输出的文档更具可读性。indent-result的缺省值为no,这是由于其他非HTML的输出格式都可能将空白认为是有意义的。
14.18 选择
XSL提供了根据输入文档来改变输出内容的两个元素。xsl:if元素根据输入文档中存在的模式,决定是否输出给定的XML段。xsl:choose元素根据输入文档中存在的模式,从几个可能的XML段中挑选一个。使用xsl:if和xsl:choose来完成的大部分任务也需要通过应用适当的模板来实现。但有时,使用xsl:if或xsl:choose来解决问题会更简单、更有效。
14.18.1 xsl:if
xsl:if元素提供了根据模式来改变输出文档的简单途径。xsl:if的test特性含有选择表达式,用来计算布尔值。如果此表达式为true,即输出xsl:if元素的内容;否则,不输出xsl:if元素的内容。例如下面的模板取消所有ATOM元素的名称。除列表中的最后一个元素外,在所有的元素后加入一个逗号和一个空格。
<xsl:template match="ATOM">
<xsl:value-of select="NAME"/>
<xsl:if test="not(position()=last())">, </xsl:if>
</xsl:template>
本模板确保列表类似于“Hydrogen, Helium"样子,而不是"Hydrogen, Helium, "的样子。
不存在xsl:else或xsl:else-if元素。xsl:choose元素提供了这一功能。
14.18.2 xsl:choose
根据几个可能的条件,xsl:choose元素从几个的输出结果中选择一个。xsl:when子元素提供各种条件及其相关的输出模板。xsl:when元素test特性为布尔值的选择表达式。如果多个条件都为真,那么只显示第一个为真的条件。如果xsl:when元素都不为真,那么显示xsl:otherwise子元素的内容。例如,下面的规则根据ATOM元素的STATE特性是为SOLID、LIQUID还是GAS,来改变输出文档的颜色:
<xsl:template match="ATOM">
<xsl:choose>
<xsl:when test="@STATE='SOLID' ">
<P style="color:black">
<xsl:value-of select="."/>
</P>
</xsl:when>
<xsl:when test="@STATE='LIQUID"'>
<P style="color:blue">
<xsl:value-of select="."/>
</P>
</xsl:when>
<xsl:when test="@STATE='GAS"'>
<P style="color:red">
<xsl:value-of select="."/>
</P>
</xsl:when>
<xsl:other>
<P style="color:green">
<xsl:value-of select="."/>
</P>
</xsl:other>
</xsl:choose>
</xsl:template>
14.19 合并多个样式单
单一XML文档可以使用在许多不同的DTD中描述的许多不同的标记符号集。有时希望将不同的标准样式单用于那些不同的符号集。但是,也可能还要将样式规则用于特定的文档。xsl:import和xsl:include元素可用来合并多个样式单,以便组织和重新将样式单用于不同的符号集和目的。
14.19.1 使用xsl:import进行录入
xsl:import元素为顶级元素,其href特性提供导入的样式单的URI。所有的xsl:import元素都必须放在xsl:stylesheet根元素中的顶级元素中。例如,下面的这些xsl:import元素导入genealogy.xsl和standards.xsl样式单。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
<xsl:import href="genealogy.xsl"/>
<xsl:import href="standards.xsl"/>
<!- other child elements follow ->
</xsl:stylesheet>
导入的样式单中的规则可能与执行导入的样式单中的规则发生冲突。如果真是这样,那么执行导入的样式单中的规则优先。如果不同的被导入样式单中的两个规则发生冲突,那么最后那个被导入的(如上面例子中的standards.xsl)优先。
xsl:apply-imports元素与xsl:apply-templates有点差别,后者只使用被导入的规则。xsl:apply-imports元素不使用执行导入的样式单中的任何规则。这样就可以访问被导入的规则,否则被导入的规则就会被执行导入的样式单中的规则所覆盖。除了名称不同外,xsl:apply-imports与xsl:apply-templates有一样的句法,唯一的作用方式差别是它只与被导入样式单中的模板规则匹配。
14.19.2 使用xsl:include进行包括
xsl:include元素也是顶级元素,它将另一个样式单复制到当前样式单中它所出现的位置处(更确切是说,它将远程文档中xsl-stylesheet元素的内容复制到当前文档中)。它的href特性提供要包括的样式单的URI。xsl:include元素可放在顶级处于最后那个xsl:import元素之后的任何地方。
不像xsl: imporlt元素所包括的规则那样,xsl:include元素所包括的规则与执行包括的样式单中的规则具有同样的优先级,利用这种优先级关系来决定是否从一个样式单到另一个样式单的复制和粘贴。对于格式化引擎来说,被包括的规则与实际存在的规则之间没有任何区别。
14.19.3 使用xsl:stylesheet在文档中嵌入样式单
可直接将XSL样式单包括在使用它的XML文档中。实际上,我不推荐这种方法,而且浏览器和格式化引擎也不一定支持这一作法。但是,有几个浏览器和格式化引擎却支持这一作法。为达此目的,xsl:stylesheet元素必须以文档元素的子元素而不是根元素本身的形式出现。它可能有一个id特性,用来为其取唯一的名称,此id特性是作为xsl:stylesheet处理指令中的href特性值的形式出现的,紧跟在的anchor(锚)标识符(#)之后。**14-20演示此过程:
**14-20:在XML文档中嵌入的XSL样式单
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="#id(mystyle)"?>
<PERIODIC_TABLE>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
id= "mystyle ">
<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="PERIODIC_TABLE">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ATOM">
<P>
<xsl:value-of select="."/>
</P>
</xsl:template>
</xsl:stylesheet>
<ATOM>
<NAME>Actinium</NAME>
<ATOMIC_WEIGHT>227</ATOMIC_WEIGHT>
<ATOMIC_NUMBER>89</ATOMIC_NUMBER>
<OXIDATION_STATES>3</OXIDATION_STATES>
<BOILING_POINT UNITS="Kelvin">3470</BOILING_POINT>
<MELTING_POINT UNITS="Kelvin">1324</MELTING_POINT>
<SYMBOL>Ac</SYMBOL>
<DENSITY_UNITS="grams/cubic centimeter"><!- At 300K ->
10.07
</DENSITY>
<ELECTRONEGATIVITY>1.1</ELECTRONEGATIVITY>
<ATOMIC_RADIUS UNITS="Angstroms">1.88</ATOMIC_RADIUS>
</ATOM>
</PERIODIC_TABLE>
14.20 本章小结
在本章,学习了有关XSL变换的内容。包括如下一些内容:
* 可扩展的样式语言(Extensible Style Language,XSL)是由两个独立的XML应用程序(分别用于转换和格式化XML文档)组成。
* XSL转换将规则应用于从XML文档中读入的一个树形结构中,以便将它转换成一个以XML文档编写的输出树形结构中。
* XSL模板规则是一个带有match特性的xsl:template元素。输入树形结构中的节点与不同模板元素match特性的模式进行比较。当找到匹配时,即输出模板的内容。
* 节点的值是含有节点内容的纯文本(不是标记),可由xsl:value-of元素获得。
* 可以由两种方法处理多个元素:xsl:apply-templates元素和xsl:for-each元素。
* xsl:template元素的match特性值是匹配模式,用以指定模板与哪个节点匹配。
* 选择表达式为match特性的超集,由xsl:apply-templates、xsl:value-of、xsl:for-each、xsl:copy-of、xsl:sort以及其他各种元素的select特性所使用。
* 两个缺省的规则将模板应用于元素节点,并取文本节点的值。
* xsl:element、xsl:attribute、xsl:pi、xsl:comment和xsl:text元素可输出元素、特性、处理指令、注释以及文本,这些输出结果都可以从输入文档中的数据进行运算获得。
* xsl:attribute-set元素定义常用的一组特性,从而使用xsl:use元素,将这组特性用于不同模板中的多个元素。
* xsl:copy元素将当前输入节点复制到输出文档中。
* xsl:number元素使用format特性所给出的指定数字格式,将expr特性中指定的数字插入到输出文档中。
* xsl:sort元素在将输入节点复制到输出文档中之前,可对输入节点重新进行排序。
* XSL不能输出CDATA部分,也不能输出未转义的<符。
* 模式可从样式单中的不同位置,将不同模板应用于相同的元素。
* xsl:variable元素定义命名的常数,以使代码清晰简练。
* 命名的模板有助于重新使用通用的模板代码。
* 在缺省的条件下,保留空白,除非用xsl:strip-space元素或xml:space特性说明为不保留。
* xsl:if元素在当且仅当其test特性为真时,才产生输出。
* 当xsl:when子元素的test特性为真时,xsl:choose元素输出其第一个xsl:when子元素的模板;或者,如果xsl:when元素都没有true的测试特性时,xsl:choose元素输出其xsl:default元素的模板。
* xsl:import和xsl:include元素合并不同样式单中的规则。
在下一章中,我们将继续XSL的另一半内容:格式化对象(formatting object)符号集。格式化对象是用来指定页面精确布局的极其强有力的手段。XSL变换用于将XML文档转换成XSL格式化对象文档。