XSLT 的角色
XSLT 的最初目的是将信息内容与 Web 显示分离。如其最初定义那样,HTML 通过按抽象概念(如段落、重点和编号列表)定义显示来实现设备独立性。随着 Web 变得越来越商业化,出版人希望其输出质量能达到与印刷品相同的质量。这逐渐导致越来越多地使用具体显示控件,如页面上材料的明确字体和绝对位置。然而不幸的是完全可以预料其副作用,即将相同的内容传递到替代设备,如数字电视机和 WAP 电话(印刷业的行话再现效果)将会变得日益困难。
由于吸收了印刷业使用 SGML 的经验,在 1998 年初定义了一种标记语言 XML,它用于表示独立于显示的结构化内容。与 HTML 使用一组固定概念(如段落、列表和表)不同,XML 标记中使用的标记完全是用户定义的,其用意是这些标记应该与所关注的对象(如人、地点、价格和日期)相关。尽管 HTML 中的元素本质上都是印刷样式(虽然处于抽象级别),而 XML 的目标是元素应该描述实际对象。例如,清单 1 显示了表示足球锦标赛结果的 XML 文档。
在 XSL 的开发过程中(这在 DSSSL 中已有所预示),发现在准备 XML 文档以备显示的过程中执行的任务可以分成两个阶段:转换和格式化。转换是将一个 XML 文档(或其内存中的表示法)转换成另一个 XML 文档的过程。格式是将已转换的树状结构转换成两维图形表示法或可能是一维音频流的过程。XSLT 是为控制第一阶段“转换”而开发的语言。第二阶段“格式化”的开发工作还是进行中。但实际上,大多数人现在使用 XSL 将 XML 文档转换成 HTML,并使用 HTML 浏览器作为格式化引擎。这是可行的,因为 HTML 实际上只是 XML 词汇表的一个示例,而 XSLT 可以使用任何 XML 词汇表作为其目标。
将转换成一种语言和格式化成另一种语言这两个操作分离经证实的确是一种好的决策,因为转换语言的许多应用程序经证明无法向用户显示文档。随着 XML 日益广泛地用作电子商务中的数据互换语法,对于应用程序将数据从一个 XML 词汇表转换成另一个 XML 词汇表的需求也在不断增加。例如,某个应用程序可能从电视收视指南中抽取电视节目的细节,并将它们插入按次付费客户的月帐单中。同样,还有许多实用的数据转换,在这些转换中源词汇表和目标词汇表是相同的。它们包括数据过滤,以及商务操作,如施行涨价。因此,随着在系统中开始越来越多地以 XML 语法的形式使用数据,XSLT 就逐渐成为由于处理这些数据的随处可见的高级语言。
在拙作中,我做了这样一个比喻:XSLT 与 XML 的关系,就好象 SQL 与表格化数据的关系一样。关系模型的强大功能并非来自用表存储数据的思想,而是源于 SQL 中可行的基于关系运算的高级数据操作。同样,XML 的层次化数据模型对应用程序开发者的帮助实际上也非常小。正是因为 XSLT 作为 XML 数据的高级操作语言提供了如此强大的功能。
XSLT 样式表是一个 XML 文档。通过使用 XML 的尖括号标记语法来表示文档的结构。这种语法在某种程度上是比较笨拙的,而此决策可以使该语言变得更罗嗦。但是,它确实有好处。它表示可以自动使用 XML 的所有词汇设备(例如,Unicode 字符编码和转义,使用外部实体等等)。它表示很容易使 XSLT 样式表变成转换的输入或输出,使该语言可以作用于自身。它还使将期望的 XML 输出块嵌入样式表变得很容易。实际上,许多简单的样式表基本上可以写作期望输出文档的模板,并且可以将一些特殊指令嵌入文本中,以便插入输入中的变量数据或计算某个值。这就使 XSLT 在这个简单的级别上非常类似于许多现有的专用 HTML 模板语言。
常常通过对 XML 文档进行语法分析来生成输入树状结构,而输出树状结构通常被串行化到另一个 XML 文档中。但 XSLT 处理器本身操作的是树状结构,而不是 XML 字符流。这个概念最初给许多用户的感觉是不切实际的,结果却对理解如何执行更复杂的转换起了关键作用。首先,它表示 XSLT 处理器可以理解源文档中与树状结构无关的特殊之处。例如,无论属性是包括在单引号中还是在双引号中,都不可能应用不同的处理,因为会将这两种形式视为同一个基本文档的不同表示方法。更深入地看,它表示处理输入元素或生成输出元素是一个原子操作。不可能将处理元素的开始标记和结束标记分成单独的操作,因为一个元素会自动表示成树模型的单节点。
<xsl:template match="results">
<html>
<head><title>
Results of Group <xsl:value-of select="@group">
</title></head>
<body><h1>
Results of Group <xsl:value-of select="@group">
</h1>
<xsl:apply-templates>
</body></html>
</xsl:template>