类和方法是面向对象程序员的工具,用于把大型应用程序组织成较小的、更加可管理的单元。XSLT 程序员为了同样的目的使用模板。当模式和当前节点匹配时,处理器就把控制交给模板。
这种模式匹配机制特别适用于处理树状结构(如 XML 文档)。从而形成了声明性的编程风格,因为避免了编写所有的树遍历和树处理例程。相反,由处理器遍历输入文档并自动为节点选择最合适的模板。
当不知道元素在输入文档中的出现顺序或者是否重复时,模式匹配特别方便。同样,处理器负责重复调用模板解决重复问题。
多数模板都是为匹配元素而编写的。当样式表处理属性时,规则通常附加在匹配元素的模板中,如清单 1 所示(本文中的所有例子都摘自 DocBook-to-HTML 样式表):
清单 1. 处理附加在元素中的属性
<xsl:template match="ulink">
<a href="{@url}"><xsl:apply-templates/></a>
</xsl:template>
|
这个模板转换
ulink 元素和
url 属性,但只与
ulink 元素匹配。
如果属性是必需的——换句话说,它一定会出现,则对元素匹配是合理的。但是如果属性是可选的,您就得在输出中生成某些内容 之前 测试该属性是否存在。有些情况下,希望通过模式中的条件进行测试,比如清单 2:
清单 2. 在模板匹配中测试属性
<xsl:template match="emphasis[@type='bold']"> <b><xsl:apply-templates/></b> </xsl:template> |
测试属性并不总是可行的。看一看 DocBook 中图片
imagedata 的标记。
imagedata
有可选的
width 和
depth 属性可能需要保存到 HTML 中。对所有可能的组合编码太困难了(
imagedata[@width] ,
imagedata[@depth] 和
imagedata[@width
and @depth] ——就是说仅仅为了
两个
属性要使用三个模板)。更合理的办法是让处理器遍历属性节点并针对属性节点编写模板,如清单 3 所示:
清单 3. 匹配属性的模板
<xsl:template match="imagedata">
<img><xsl:apply-templates select="@*"/></img>
</xsl:template>
<xsl:template match="@width">
<xsl:attribute name="width">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@depth">
<xsl:attribute name="height">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@fileref">
<xsl:attribute name="href">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
|
注意,处理器默认是不遍历属性节点的。必须使用
select="@*" 属性明确地要求这样做。
匹配元素的模板和匹配属性的模板有两个重要的区别:
-
属性是叶子。
xsl:apply-templates指令什么地方也去不了,因为属性没有子女可供处理器遍历。应该使用xsl:value-of。 -
输入中的多数属性在输出中仍然是属性。使用
xsl:attribute向输出树中插入属性。但是要小心,因为xsl:attribute必须出现在其他任何子女之前。换句话说,xsl:apply-templates指令必须在调用者的任何文本或子元素之前使用。
匹配属性赋予您完整的 XSLT 表达能力。模板并不仅限于把属性转换成另一个属性。可以向模式中增加条件或者把属性转换成元素。清单 4 中的模板定义了一个特殊的规则,以匹配
fileref
作为 videodata 的一个属性。它创建的是一个元素而非属性。
清单 4. 匹配带条件的属性
<xsl:template match="videodata/@fileref">
<param name="src" value="{.}"/>
</xsl:template>
|
此外,还可以在调用者中通过
select="@* | node()" 属性把模板应用于属性和元素内容,如清单 5
所示:
清单 5. 调用模板处理元素和属性
<xsl:template match="para"> <p><xsl:apply-templates select="@* | node()"/></p> </xsl:template> |
这个技巧是 XSLT 编码中更一般原则的实际例子:为了使样式表更加可维护,把工作分到几个模板中是值得的。
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 请参与 Benoit Marchal “使用XML”专栏的
讨论论坛。
- 试一试 Xalan,可以在
Apache
XML Project站点上找到。Xalan 仍然是最受欢迎的 XML 处理器之一。
- 访问 Dave Pawson 维护的
XSL
FAQ,这是回答常见问题的很好的资源站。
- 如果曾经被 XSL 病毒伤害过,您就会喜欢
Gallery
of Stupid XSL and XSLT Tricks,这是关于 XSL/XSLT 不寻常的、有趣的窍门汇编(也许您猜到了)。
- XSLT 入门教程——“
用 XSL 操作数据”,Nicholas Chase (
developerWorks
, 2001 年 10 月)。
- 阅读“
XSLT 是什么类型的语言?”,看看 Michael Kay 关于 XSLT 语言及其模板实现的讨论(
developerWorks,
2001 年 2 月)。
- 在
developerWorks
XML
专区上查找 XML 的资源。关于最新的 XML 技巧的完整列表,请查看
实用技巧。
- 了解如何成为一名
IBM
认证的 XML 及相关技术的开发人员。

Benoit Marchal是一位比利时籍顾问。他是 XML by Example, Second Edition 和其他 XML 书籍的作者。您可以向 Benoit 寻求有关 XML 项目的帮助——可以通过 bmarchal@pineapplesoft.com 或他的个人站点 marchal.com 与他联系。