深入XSL(4)
---模板
翻译:孙一中
1 概述
当使用于源元素的规则被确定后,就要具体实现该规则的模板.一个模板能包含文字结果的元素, 字符数据和产生结果树部分的指令.指令由XSL名域中的元从来表示,可以选择后代元从来处理. 有两类这样的指令, xsl:process-children 和xsl:process; xsl:process-children指令处理源元素的邻近子元素, 而xsl:process指令处理由指定模式来选择的元素.见下例:
<xsl:template match="chapter/title">
<fo:rule-graphic/>
<fo:block space-before="2pt">
<xsl:text>Chapter </xsl:text>
<xsl:number/>
<xsl:text>: </xsl:text>
<xsl:process-children/>
</fo:block>
<fo:rule-graphic/>
</xsl:template>
2 文字结果元素
在一个模板中,款式表中不属于XSL名域的元素具体化将产生相反类型的节点;生成的元素节点会有曾经对在模板树中的元素规定的属性. 文字结果元素的一个属性的值被认为是一个属性值模板:它能包含在花括号({})中的字符串. 结果元素节点的名域前缀映射是在款式表中移去映射到XSL名域的URI后的映射.由于XSL处理器只作用于属于XSL名域的元素,所以就有这样的问题:如何新建属于XSL名域的元素?URI是http://www.w3.org/TR/WD-xsl的名域如果紧接出现一个或多个的/quote成为被援用的名域.使用名域将作特殊处理.
3 命名属性集
xsl:define-attribute-set元素定义了一自命名的属性集合. "name"属性规定了属性集的名称. xsl:define-attribute-set元素的内容是一个规定属性的xsl:attribute-set元素.一个文字结果元素或者一个xsl:attribute-set元素能指定一属性集名称为xsl:use属性的值.下面的例子产生了一个称为title-style的属性集并在模板规则中使用它.
<xsl:define-attribute-set name="title-style">
<xsl:attribute-set font-size="12pt" font-weight="bold"/>
</xsl:define-attribute-set>
<xsl:template match="chapter/heading">
<fo:block xsl:use="title-style" quadding="start">
<xsl:process-children/>
</fo:block>
</xsl:template>
4 模板中的文字
模板也能包含PCDATA(Parsed Character Data). 在模板中去除空格后的每个数据字符将在结果树中产生一个数据字符.文字的数据字符也可以包装在一个xsl:text元素中.这样的包装处理可能改变空格的去除但不影响XSL处理器对字符的处理.
5 xsl:process-children的处理
下例新建用于chapter元素的块(block) 并处理它的相邻子元素.
<xsl:template match="chapter">
<fo:block>
<xsl:process-children/>
</fo:block>
</xsl:template>
xsl:process-children指令处理当前节点的所有子节点,包括字符. 处理源树中的字符是将字符添加到结果树.因此,其中的<标记在源树中表示<字符,该源树将由内置的模板规则在结果树中转换为<字符,而当结果树具体化为一个XML文档时,<字符又将表示为< .
6 xsl:process的处理
xsl:process元素处理由一个模式选择的元素. xsl:process 元素的模式是一个选择模式,因此它被间接地定位到当前节点.下面的例子对author-group的所有author子节点进行处理:
<xsl:template match="author-group">
<fo:sequence>
<xsl:process select="author"/>
</fo:sequence>
</xsl:template>
xsl:process元素处理所有婚配规定模式的元素.字符数据不被xsl:process元素婚配.模式不能包含属性模式(AttributePattern)除非它作为属性限定(AttributeQualifier)的一部分. 模式控制了发生婚配的深度.下例处理所有author节点中first-name元素:
<xsl:template match="author-group">
<fo:sequence>
<xsl:process select="author/first-name"/>
</fo:sequence>
</xsl:template>
在模式中使用//操作符可以婚配任意的深度. 下例处理在book元素中的所有heading元素.
<xsl:template match="book">
<fo:block>
<xsl:process select=".//heading"/>
</fo:block>
</xsl:template>
7 直接处理
当结果是已知的规则结构,能够直接确定选择元素的模板是很无益的. xsl:for-each元素包括一个模板,它具体实现由select属性规定的每个选择元素.比如对下面的XML文档:
<customers>
<customer>
<name>...</name>
<order>...</order>
<order>...</order>
</customer>
<customer>
<name>...</name>
<order>...</order>
<order>...</order>
</customer>
</customers>
下面的XSL将生成一个HTML文档,包括一个表格,其中的一行就为一个custom元素
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE>Customers</TITLE>
</HEAD>
<BODY>
<TABLE>
<TBODY>
<xsl:for-each select="customers/customer">
<TR>
<TH>
<xsl:process select="name"/>
</TH>
<xsl:for-each