65.9K
CodeProject 正在变化。 阅读更多。
Home

XSLT 程序员参考手册 第二版

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (12投票s)

2001 年 9 月 4 日

78分钟阅读

viewsIcon

120943

本章将介绍 XSLT 的目的以及它被设计来执行的任务。

Sample Image
标题 XSLT 程序员参考手册 第二版
作者 Michael Kay
出版社 Wrox
出版日期 2001 年 4 月
ISBN 1861005067
价格 34.99 美元
页数 900

XSLT 的背景

本章旨在将 XSLT 置于背景中。它关于 XSLT 的目的以及它被设计来执行的任务。它关于它是一种什么样的语言,以及它是如何演变成这样的;它还关于 XSLT 如何与您在典型的基于 Web 的应用程序中可能使用的所有其他技术相协调。在本章中,我不会详细介绍 XSLT 样式表实际上看起来是什么样的,或者它是如何工作的:这将在第 2 章和第 3 章中讨论。

我将首先描述 XSLT 被设计来执行的任务——转换——以及为什么需要转换 XML 文档。然后,我将提供一个微不足道的转换示例,以解释这在实践中意味着什么。

然后,本章将继续讨论 XSLT 与日益增长的 XML 系列中其他标准的关系,以将其功能置于背景中,并解释它如何补充其他标准。

我将描述 XSLT 是一种什么样的语言,并稍微深入探讨它如何演变成这样的历史。如果您不耐烦,您可能想跳过历史,开始使用这门语言,但迟早您会问“他们为什么会这样设计它?”届时,我希望您能回顾一下 XSLT 的产生过程。

最后,我将谈谈在应用程序的整体架构中使用 XSLT 的不同方式,其中不可避免地会有许多其他技术和组件各自发挥作用。

什么是 XSLT?

XSLT(eXtensible Stylesheet Language: Transformations 的缩写)是一种语言,根据规范(可在 http://www.w3.org/TR/xslt 找到)的第一句话,它主要用于将一个 XML 文档转换为另一个 XML 文档。然而,XSLT 完全有能力将 XML 转换为 HTML 和许多其他文本格式,因此更通用的定义可能如下:

XSLT 是一种用于转换 XML 文档结构的语言。

你为什么要这样做?为了正确回答这个问题,我们首先需要回顾一下为什么 XML 如此成功并引起了如此多的关注。

为什么要转换 XML?

XML 是一种简单、标准的方式,可以在计算机程序之间交换结构化文本数据。它的成功部分原因在于它也能被人类读写,只需一个文本编辑器即可完成,但这并不能改变它主要用于软件系统之间通信的事实。因此,XML 满足了两个迫切的需求:

  • 将数据与表示分离。需要将信息(如天气预报)与在特定设备上如何呈现它的细节分离开来。随着支持互联网的设备范围不断扩大,这一需求变得越来越紧迫。已投资创建有价值信息源的组织需要能够不仅将其提供给传统的基于 PC 的 Web 浏览器(它本身现在有许多版本),还能提供给电视机和 WAP 手机,更不用说继续需要生成打印件了。

  • 在应用程序之间传输数据。需要将信息(如订单和发票)从一个组织传输到另一个组织,而无需投资于定制软件集成项目。随着电子商务的加速,企业之间交换的数据量每天都在增加,这一需求变得越来越紧迫。

当然,这两种使用 XML 的方式并非相互排斥。发票可以在屏幕上显示,也可以输入到财务应用程序包中,天气预报可以由接收者进行摘要、索引和聚合,而不是直接显示。XML 的另一个关键好处是它统一了文档和数据世界,提供了一种表示结构的单一方式,无论信息是供人类还是机器使用。主要一点是,无论 XML 数据最终是由用户还是软件应用程序使用,它很少会以到达时的形式直接使用:它必须先转换为其他内容。

为了与人类读者进行通信,这种其他内容可能是一个可以显示或打印的文档:例如 HTML 文件、PDF 文件,甚至是声音。将 XML 转换为 HTML 进行显示可能是当今 XSLT 最常见的应用,也是本书中大多数示例将使用的。一旦数据采用 HTML 格式,任何浏览器都可以显示它。

为了在不同应用程序之间传输数据,我们需要能够将数据从一个应用程序使用的数据模型转换为另一个应用程序使用的数据模型。要将数据加载到应用程序中,所需的格式可能是逗号分隔值文件、SQL 脚本、HTTP 消息,或者对特定编程接口的一系列调用。或者,它可能是使用与原始文档不同的词汇表的另一个 XML 文件。随着基于 XML 的电子商务的普及,XSLT 在应用程序之间的数据转换中的作用也变得越来越重要。仅仅因为每个人都在使用 XML,并不意味着数据转换的需求就会消失。总会有多种标准在使用。例如,报纸行业可能会使用不同于广播行业使用的格式来交换新闻文章。同样,总会有需要进行诸如从采购订单中提取地址并将其添加到发票之类的事情。因此,将企业链接起来进行电子商务将越来越多地成为定义如何从一组 XML 文档中提取和组合数据以生成另一组 XML 文档:XSLT 是完成这项工作的理想工具。

在本章末尾,我们将回到关于何时应使用 XSLT 转换 XML 的具体示例。现在,我只是想建立一种对转换 XML 的重要性和有用性的感觉。在我们继续详细讨论 XSLT 并首次了解其工作原理之前,让我们来看一个清楚演示我们可以将 XML 转换为各种格式的示例,使用 XSLT。

示例:转换音乐

http://www.xml.org/xmlorg_registry/index.shtml 上有一个出色的 XML 词汇表和模式注册表。

如果您在那里查看,您会发现有半打不同的 XML 模式用于描述音乐。这些都是为了不同的目的而设计的:用于出版商打印乐谱的标记语言与用于让您从浏览器中收听音乐的标记语言的要求不同。例如,MusicML 侧重于图形化显示音乐符号;ChordML 用于编码声乐歌词的和声伴奏;MusicXML 用于表示乐谱,特别是 17 世纪及以后西方音乐记谱法,而普利托利亚大学的更为学术化的 Music Markup Language (MML) 用于严肃的音乐学分析,涵盖东方、非洲以及西方音乐习语。


因此,您可以使用 XSLT 以多种不同的方式处理标记的音乐:

  • 您可以使用 XSLT 将音乐从一种表示形式转换为另一种,例如从 MusicXML 转换为 MML。
  • 您可以使用 XSLT 将音乐从任何一种表示形式转换为视觉音乐符号,通过生成基于 XML 的矢量图形格式 SVG。

  • 您可以使用 XSLT 通过生成 MIDI(Musical Instrument Digital Interface)文件,在合成器上播放音乐。

  • 您可以使用 XSLT 执行音乐转换,例如将音乐移调到不同的音调。

  • 您可以将歌词提取到 HTML 或纯文本 XML 文档中。

您可以看到,XSLT 不仅仅用于将 XML 文档转换为 HTML!

XSLT 如何转换 XML?

到目前为止,您可能想知道 XSLT 究竟是如何处理 XML 文档以将其转换为所需输出的。这个过程通常有两个方面:

  • 第一阶段是结构转换,其中数据从传入的 XML 文档的结构转换为反映所需输出的结构。
  • 第二阶段是格式化,其中新结构以所需的格式(如 HTML 或 PDF)输出。

第二阶段涵盖了我们在上一节中讨论的范围;第一阶段产生的数据结构可以作为 HTML、文本文件或 XML 输出。HTML 输出允许用户直接在浏览器中查看信息,或输入到任何现代文字处理器。纯文本输出允许数据以现有应用程序可以接受的方式格式化,例如逗号分隔值或 XML 出现之前开发的许多基于文本的数据交换格式之一。最后,XML 输出允许将数据提供给接受 XML 的新型应用程序。通常,这会使用与原始文档不同的 XML 标记词汇表:例如,XSLT 转换可能以月度销售数字作为其 XML 输入,并以 SVG(一种基于 XML 的矢量图形标准)作为其 XML 输出,生成直方图。或者,您可以使用 XSLT 转换来生成 VoxML 输出,以实现数据的语音呈现。

有关 Motorola 的 VoxML Voice Markup Language 的信息链接可以在 http://www.oasis-open.org/cover/voxML.html 找到。

现在让我们深入到第一个阶段,转换——这是

XSLT 主要关注的阶段,它使得能够提供所有这些格式的输出。此阶段可能涉及选择数据、聚合和分组数据、排序数据,或执行算术转换,例如将厘米转换为英寸。

那么这是如何发生的呢?在 XSLT 出现之前,您只能通过编写自定义应用程序来处理传入的 XML 文档。该应用程序实际上不需要解析原始 XML,但它需要通过定义的应用程序编程接口 (API) 调用 XML 解析器,以从文档中获取信息并进行处理。有两种主要的 API 可以实现这一点:XML 的简单 API (SAX) 和文档对象模型 (DOM)。

SAX API 是一个基于事件的接口,其中解析器在读取文档时将文档中的每条信息通知应用程序。如果您使用 DOM API,则解析器会检查文档并在内存中构建一个类似树的对象结构。然后,您将编写一个自定义应用程序(例如,使用 C++、Visual Basic 或 Java 等过程式语言),它可以检查此树结构。它将通过定义要遵循的一系列特定步骤来实现此目的,以生成所需的输出。因此,无论您使用哪种解析器,此过程都存在相同的首要缺点:每次要处理一种新的 XML 文档时,您都必须编写一个新的自定义程序,描述不同的处理步骤来处理 XML。

DOM 和 SAX API 在 Wrox Press 出版的《Professional XML》(ISBN 1-861003-11-0)一书中都有完整描述。

那么,使用 XSLT 执行 XML 转换与编写“自定义应用程序”相比有什么优势呢?嗯,XSLT 的设计基于这样一个认识:这些程序都非常相似,因此应该可以使用一种高级声明式语言来描述它们所做的事情,而不是从头开始用 C++、Visual Basic 或 Java 编写每个程序。所需的转换可以表示为一组规则。这些规则基于在输入中出现特定模式时要生成的输出。该语言是声明式的,意味着您描述所需的转换,而不是提供一系列过程指令来实现它。XSLT 描述所需的转换,然后依赖 XSLT 处理器来决定最有效的执行方式。

XSLT 仍然依赖于 XML 解析器——无论是 DOM 解析器还是兼容 SAX 的解析器——将 XML 文档转换为树结构。XSLT 操作的是此文档的树表示的结构,而不是文档本身。如果您熟悉 DOM,那么您会对将 XML 文档中的每个项(元素、属性、处理指令等)视为树中的节点这一想法感到满意。使用 XSLT,我们有一种高级语言,可以遍历节点树,选择特定节点,并对这些节点执行复杂的处理。

XSLT 树模型在概念上与 DOM 类似,但并不相同。完整的 XSLT 处理模型将在第 2 章中讨论。

到目前为止对 XSLT 的描述(一种声明式语言,可以导航和选择特定数据,然后操纵该数据)可能让您觉得它与标准数据库查询语言 SQL 相似。让我们仔细看看这个比较。

XSLT 和 SQL:类比

我喜欢用关系数据库来做类比。在关系数据库中,数据由一组表组成。表本身用处不大,数据就像存储在逗号分隔值格式的平面文件中一样。关系数据库的力量不在于其数据结构;它在于处理数据的语言,即 SQL。同样,XML 本身只定义了一个数据结构。它比关系模型中的表更丰富,但本身并没有什么非常有用的功能。当我们得到一种专门用于操纵数据结构的高级语言时,我们才开始发现我们拥有的东西很有趣,而对于 XML 数据来说,这种语言就是 XSLT。

表面上看,SQL 和 XSLT 是截然不同的语言。但如果您深入了解,它们实际上有很多共同点。首先,为了处理特定数据,无论是关系数据库中的数据还是 XML 文档中的数据,处理语言都必须包含声明式查询语法,用于选择需要处理的数据。在 SQL 中,这是 SELECT 语句。在 XSLT 中,等价物是 XPath 表达式。

XPath 表达式语言是 XSLT 的一个重要组成部分,尽管它实际上是在一个单独的 W3C 推荐(http://www.w3.org/TR/xpath)中定义的,因为它也可以独立于 XSLT 使用(XPath 和 XSLT 之间的关系将在第 26 页进一步讨论)。

XPath 查询语法旨在根据 XML 文档中的路径或节点出现的上下文从 XML 文档中检索节点。它允许访问特定节点,同时保留文档的层次结构。然后,XSLT 用于操纵这些查询的结果(重新排列选定的节点、构造新节点等)。

XSLT 和 SQL 之间还有更多相似之处:

  • 这两种语言都通过有用的附加功能来增强基本的查询功能,以执行基本的算术、字符串操作和比较操作。

  • 这两种语言都通过半过程性功能来补充声明式查询语法,以描述要执行的处理顺序,并且它们还提供了连接到常规编程语言的钩子,在算法变得过于复杂时可以使用。


  • 这两种语言都具有一个重要的属性,称为 **闭包**,这意味着输出具有与输入相同的数据结构。对于 SQL17 来说,这种结构是表;对于 XSLT 来说,它是树——XML 文档的树形表示。闭包属性非常有价值,因为它意味着使用该语言执行的操作可以端到端地组合起来以定义更大、更复杂的操作:只需将一个操作的输出作为下一个操作的输入。在 SQL 中,您可以通过定义视图或子查询来实现这一点;在 XSLT 中,您可以通过将数据通过一系列样式表,或者(使用新的 XSLT 1.1 规范,目前是工作草案)将一个转换阶段的输出捕获为临时树,并将该临时树用作另一个转换阶段的输入来实现。

在现实世界中,XSLT 和 SQL 当然必须共存。存在许多可能的组合关系,但通常数据将存储在关系数据库中,并在系统之间以 XML 形式传输。这两种语言不像人们希望的那样舒适地结合在一起,因为它们的数据模型非常不同。但是 XSLT 转换可以在弥合分歧方面发挥重要作用。许多数据库供应商已经推出了集成 XML 和 SQL 的产品,尽管该领域尚无标准。请查看供应商的网站,了解 Microsoft SQL Server 2000 和 Oracle 9i 的最新版本。

在我们继续查看一个简单的 XSLT 转换工作示例之前,我们需要简要讨论一些可用于实现这些转换的 XSLT 处理器。

XSLT 处理器

XSLT 处理器的主要作用是将 XSLT 样式表应用于 XML 源文档并生成结果文档。重要的是要注意,这些都是 XML 的应用,因此它们的底层结构都是树。所以,实际上,XSLT 处理器处理的是三棵树。

有几种 XSLT 处理器可供选择。我在此将提及三个:Saxon、Xalan 和 Microsoft MSXML3。所有这些都可以免费下载(但请阅读许可条件)。

这三个处理器和几个其他处理器将在本书的附录中详细介绍。

Saxon 是本书作者开发的开源 XSLT 处理器。它是一个 Java 应用程序,可以直接从命令行运行;无需 Web 服务器或浏览器。Saxon 程序会将 XML 文档转换为 HTML 文档(举例),然后可以将其放在 Web 服务器上。在此示例中,浏览器和 Web 服务器都只处理转换后的文档。

如果您运行 Windows(95/98/NT/2000),使用它的最简单方法是下载 Instant Saxon,它被打包成一个 Windows 可执行文件。您需要安装 Java,但如果您有任何最近版本的 Internet Explorer,它应该已经安装了。在非 Windows 平台上,您需要安装完整的 Saxon 产品并遵循附带的说明。您可以从 http://users.iclway.co.uk/mhkay/saxon/index.html 免费下载 Instant Saxon。Saxon 可以与任何实现 SAX2 接口(Java 形式)的 XML 解析器一起运行,但它附带了一个 Ælfred 解析器副本,因此您无需单独安装一个。

Xalan 是另一个开源 XSLT 处理器,可从 Apache 组织获取,网址为 http://xml.apache.org/。Xalan 最初源自 IBM 的 LotusXSL 产品,但此后发展出了自己的开源生命。Xalan 有 Java 和 C++ 版本。与 Saxon 一样,Xalan-Java 是一个可以从命令行运行的 Java 应用程序。Xalan 也可以与任何兼容 SAX2 的解析器一起工作;它附带了一个同伴解析器 Xerces 的副本。

Saxon 和 Xalan-Java 都实现了相同的 Java 接口,称为 TrAX,我将在附录 F 中进行描述:这意味着您可以编写同时适用于这两个处理器的应用程序。两者都高度符合 XSLT 1.0 规范,因此您的样式表将完全可移植;但它们在标准要求之外的功能方面有所不同。本书的附录中更全面地描述了这两个产品。

或者,您实际上可以在 Internet Explorer 中运行 XSLT 样式表。IE5 和 IE5.5 的生产版本附带了一个处理器,该处理器处理微软的 XSLT 方言,该方言松散地基于 1998 年初的 W3C 规范工作草案:这种语言(我称之为 *工作草案 XSL* 或 *WD-xsl*)与最终版本有很大不同,我强烈建议您避免使用它。微软现在提供了一个完全符合最终 XSLT 1.0 规范的实现,称为 MSXML3。最终,这可能会作为 Internet Explorer 6 的标准版本提供,但在此期间,您可以从 http://msdn.microsoft.com 单独下载它,并安装以供 IE5 或 IE5.5 使用。

下载并安装 SDK 和运行时包。您还应该下载并安装一个名为 xmlinst.exe 的程序。运行此程序以将 MSXML3 设置为 Internet Explorer 使用的默认 XML 处理器(如果您不这样做,IE5 将尝试使用旧的 WD-xsl 处理器)。微软技术的最大优势在于 XSLT 处理可以在浏览器中进行。

我在这本书的大部分内容中都避免讨论具体产品,因为信息可能会变化很快。我在附录中描述的产品现在相对稳定,但新产品不断涌现。最好从网上获取最新状态。一些不错的起点是:

一个示例样式表

现在我们准备查看一个使用 XSLT 转换非常简单的 XML 文档的示例。

示例:“Hello, world!” XSLT 样式表

Kernighan 和 Ritchie 在他们经典的《C 编程语言》中提出了在书的开头展示一个微小但完整的程序的主意,从那时起,“Hello world”程序就成了一种光荣的传统。当然,对这个示例如何工作的完整描述是不可能的,直到所有概念都定义清楚为止,所以如果您觉得我没有完全解释清楚,请不要担心——解释将在后面。

输入

我们想做什么样的转换?让我们尝试转换以下 XML 文档:

<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="hello.xsl"?>
<greeting>Hello, world!</greeting>

此文档的简单节点树表示将如下所示:

每个文档只有一个根节点。XSLT 模型中的根节点执行与 DOM 模型中的文档节点相同的功能。XML 声明对解析器不可见,因此不包含在树中。

我故意通过在源 XML 文件中包含一个 <?xml-stylesheet?> 处理指令来使其变得容易。许多 XSLT 处理器将使用它来识别样式表,如果您不指定不同的样式表来使用。href 属性给出了此文档的默认样式表的相对 URI。

输出

我们所需的输出是以下 HTML,它将仅将浏览器标题更改为“Today's Greeting”,并显示源 XML 文件中的问候语:

<html>
<head>
   <title>Today's greeting</title>
</head>
<body>
   <p>Hello, world!</p>
</body>
</html>

XSLT 样式表

废话不多说,这是实现转换的 XSLT 样式表 hello.xsl:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
   <html>
   <head>
      <title>Today's greeting</title>
   </head>
   <body>
      <p><xsl:value-of select="greeting"/></p>
   </body>
   </html>
</xsl:template>
</xsl:stylesheet>

运行样式表

您可以使用上一节中描述的任何三个处理器运行此样式表。

Saxon

对于 Saxon,步骤(对于 Windows 平台)是:

  • 下载 Instant Saxon 处理器

  • 将可执行文件 saxon.exe 安装到合适的目录,并将其设为当前目录

  • 使用记事本,在当前目录中分别将上述两个文件键入 hello.xml 和 hello.xsl(或从 Wrox 网站 http://www.wrox.com 获取它们)。

  • 打开一个 MSDOS 风格的控制台窗口(在 Windows 98 或 NT 上使用“开始 | 程序 | MSDOS 提示”,或在 Windows 2000 的“附件”菜单中查找)。

  • 在命令提示符下键入以下命令:
    saxon hello.xml hello.xsl

  • 欣赏标准输出上显示的 HTML。

如果您想使用浏览器查看输出,只需将命令行输出保存为 HTML 文件,方法如下:

saxon hello.xml hello.xsl >hello.html

因为您使用的是此源 XML 文档的默认样式表,所以您也可以这样写:

saxon -a hello.xml >hello.html

Xalan-Java

如果您使用 Xalan-Java,过程非常相似。但是,Xalan 没有像 Saxon 那样为 Windows 平台打包的特殊版本,因此您必须显式地在 Java 下运行应用程序(如果您使用完整版本,也可以对 Saxon 执行此操作)。

您需要安装 Java 虚拟机。Xalan 不支持 Internet Explorer 附带的 Microsoft 虚拟机(因为它需要 Java 早期版本的功能),因此您需要单独安装。我通常使用 Sun 的 JDK 1.3,您可以从 http://java.sun.com/j2se/1.3/ 获取。安装过程非常简单,尽管下载文件很大。

下载 Xalan-Java 2 作为 .zip 文件后,您需要将其解压到合适的目录。有两个重要文件必须对 Java 虚拟机可访问。它们是 xalan.jar(包含 XSLT 处理器的代码)和 xerces.jar(包含 XML 解析器),它们都位于 bin 目录中。要告诉 Java VM 在哪里可以找到这些文件,它们必须存在于 CLASSPATH 环境变量中。您可以在 autoexec.bat 文件或您的操作系统登录时执行的任何其他脚本中设置此变量;在 Windows NT 和 Windows 2000 上,您可以使用控制面板中的 System 图标来设置环境变量。另一种方法是将类路径作为调用应用程序的命令的一部分输入。

我通常将所有需要的 .jar 文件移动到一个目录,如 c:\jars,然后设置类路径如下:

SET CLASSPATH=.;c:\jars\xalan.jar;c:\jars\xerces.jar

请注意,必须是 .jar 文件本身在类路径上,而不是包含它们的目录。

那么,在 Xalan 下运行“hello world”转换的命令是:

java org.apache.xalan.xslt.Process -in hello.xml -xsl hello.xsl

它应该产生与 Saxon 相同的结果。因为您使用的是默认样式表,所以您可以将其简化为:

java org.apache.xalan.xslt.Process -in hello.xml

如果您想将输出定向到特定文件,请使用 -out 选项。

MSXML3

最后,您实际上可以在 Internet Explorer 中运行样式表。

安装 MSXML3 作为默认 XSLT 处理器后,您应该只需双击 hello.xml 文件,这将在 IE5 中打开 hello.xml 文件。IE5 读取 XML 文件,发现需要哪个样式表,加载样式表,执行它以执行转换,并显示生成的 HTML。如果您在屏幕上看不到“Hello, world!”文本,而只看到 XML 文件,这是因为您使用的是微软随 IE5 发布的原始 WD-xsl 解释器,而不是 MSXML3 版本。如果您看到显示的样式表,这也表明您尚未正确完成安装过程。请记住运行 xmlinst.exe 程序。

工作原理

如果您成功运行了这个示例,或者即使您只想继续阅读本书,您也会想知道它是如何工作的。让我们来分析一下:

<?xml version="1.0" encoding="iso-8859-1"?>

这只是标准的 XML 标题。有趣的是,XSLT 样式表本身就是一个 XML 文档。我稍后将在本章中进一步讨论这个问题。我使用了 iso-8859-1 字符编码(这是微软有时称为“ANSI”的字符集的官方名称),因为在西欧和北美,这是大多数文本编辑器支持的字符集。如果您有一个支持 UTF-8 或其他字符编码的文本编辑器,请随时使用它。

<xsl:stylesheet

   version="1.0">

   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

这是标准的 XSLT 标题。就 XML 而言,这是一个元素开始标签,它将文档标识为样式表。xmlns:xsl 属性是一个 XML 命名空间声明,它表示前缀 xsl 将用于 W3C XSLT 规范中定义的元素。XSLT 大量使用 XML 命名空间,并且标准中定义的所有元素名称都带有此命名空间前缀,以避免与源文档中使用的名称发生冲突。version 属性表明样式表仅使用 XSLT 标准 1.0 版本的功能。

我们继续

<xsl:template match="/">

一个 <xsl:template> 元素定义了一个模板规则,当处理源文档的特定部分时将被触发。match="/" 属性表示此特定规则在处理源文档的开始时被触发。“/”是一个 XPath 表达式,它标识文档的根节点:XML 文档具有层次结构,就像 UNIX 使用特殊文件名“/”来表示层次文件存储的根一样,XPath 使用“/”来表示 XML 内容层次的根。DOM 模型称之为 Document 对象,但在 XPath 中称为根。

<html>
<head>
   <title>Today's greeting</title>
</head>
<body>
   <p><xsl:value-of select="greeting"/></p>
</body>
</html>

一旦触发此规则,模板的主体就决定了要生成什么输出。这里的大部分模板主体是一系列 HTML 元素和文本,将被复制到输出文件中。有一个例外:<xsl:value-of> 元素,我们将其识别为 XSLT 指令,因为它使用了命名空间前缀 xsl。此特定指令将源文档节点的*值*复制到输出文档。该元素的 select 属性指定应为其求值值的节点。XPath 表达式“greeting”表示:“找到与当前正在处理此模板规则的节点相邻的所有 greeting 元素的集合”。在这种情况下,这意味着 greeting 元素是源文档的最外层元素。然后,<xsl:value-of> 指令提取此元素的文本节点,并将其复制到输出的相关位置,即在生成的 <p> 元素内。

剩下的就是完成我们开始的工作:

</xsl:template>
</xsl:stylesheet>

事实上,对于像上面所示的简单样式表,您可以省去一些繁琐的步骤。由于只有一个模板规则,因此可以省略 <xsl:template> 元素。以下是一个完整的、有效的样式表,等同于前面的一个:

<html xsl:version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<head>
   <title>Today's greeting</title>
</head>
<body>
   <p><xsl:value-of select="greeting"/></p>
</body>
</html>

这种简化的语法旨在使 XSLT 对那些学会使用专有模板语言的人来说看起来很熟悉,这些模板语言允许您编写一个 HTML 页面骨架,其中包含特殊标签(类似于 <xsl:value-of>)以在适当的位置插入变量数据。但正如我们将看到的,XSLT 比这强大得多。

您为什么要将今天的问候语放在单独的 XML 文件中并使用样式表显示它?一个原因是您可能希望根据上下文以不同的方式显示问候语;例如,它可能在不同的设备上显示不同。在这种情况下,您可以编写一个不同的样式表来以不同的方式转换同一个源文档。这就提出了在运行时如何选择样式表的问题。这个问题没有单一的答案。如上所述,Saxon 和 Xalan 提供了可以指定样式表和源文档的接口。使用 Microsoft XSLT 产品也可以实现这一点,尽管它要求您编写一个包含脚本代码的 HTML 页面来控制转换:我在上面示例中使用的 <?xml-stylesheet?> 处理指令只有在您想每次都使用同一样式表时才有效。

现在是时候仔细看看 XSLT 与 XPath 以及其他 XML 相关技术之间的关系了。

XSLT 在 XML 系列中的位置

XSLT 由万维网联盟 (W3C) 发布,并属于 XML 标准系列,其中大部分也由 W3C 开发。在本节中,我将尝试解释 XSLT 与其他相关标准和规范之间有时令人困惑的关系。

XSLT 和 XSL

XSLT 最初是作为一种名为 XSL(Extensible Stylesheet Language)的更大型语言的一部分。顾名思义,XSL(并且仍然)旨在定义 XML 文档在屏幕、纸张或口语上的格式化和呈现。随着 XSL 的发展,人们发现这通常是一个两阶段过程;首先是结构转换,其中选择、分组和重新排序元素,然后是格式化过程,其中将生成的元素渲染为纸上的墨迹或屏幕上的像素。人们认识到这两个阶段是相对独立的,因此 XSL 被拆分为两部分:XSLT 用于定义转换,而“其余部分”——仍然官方称为 XSL,尽管有些人喜欢称之为 XSL-FO(XSL Formatting Objects)——用于格式化阶段。

XSL 格式化不过是另一种 XML 词汇表,其中描述的对象是页面区域及其属性。由于这只是另一种 XML 词汇表,XSLT 不需要任何特殊功能来生成它作为输出。XSL 格式化超出了本书的范围。这是一个庞大的主题(当前可用的草案规范比 XSLT 长得多),标准尚未完全最终确定,实现它的产品仍不完整。此外,您需要它的可能性远低于需要 XSLT。XSL 格式化提供了出色的功能,可实现文档的高质量排版输出。然而,对大多数人来说,将文档转换为 HTML 以供标准浏览器呈现就足够了,这可以通过单独使用 XSLT 来实现,或者在必要时,将 XSLT 与级联样式表 (CSS 或 CSS2) 结合使用,我稍后将回到这一点。

XSL 格式化规范(撰写本文时处于候选推荐状态)可在 http://www.w3.org/TR/xsl 找到。候选推荐规范是 W3C 已发布供最终评论的规范,当这些评论得到处理后,它通常会成为正式推荐。XSL 格式化对象成为正式推荐的条件还需要证明其所有构造都已成功实现,并且不同实现之间是可互操作的。

XSLT 和 XPath

在 XSLT 开发过程中,人们认识到 XSLT 中用于选择文档部分的表达式语法与正在开发的用于从一个文档链接到另一个文档的 XPointer 语言之间存在显著重叠。为了避免两种独立但重叠的表达式语言,两个委员会决定联手定义一种语言——XPath,它将服务于这两个目的。XPath 1.0 版于 1999 年 11 月 16 日与 XSLT 同一天发布。

XPath 在 XSLT 样式表中充当子语言。XPath 表达式可用于数值计算或字符串操作,或用于测试布尔条件,但其最典型的用途(也是其名称的由来)是识别要处理的输入文档的部分。例如,以下指令输出输入文档中所有书籍的平均价格:

<xsl:value-of select="sum(//book/@price) div count(//book)"/>

这里的 <xsl:value-of> 元素是 XSLT 标准中定义的指令,它会导致将一个值写入输出文档。select 属性包含一个 XPath 表达式,该表达式计算要写入的值:具体来说,是所有 book 元素上的 price 属性的总和,除以 book 元素的数量。

XPath 规范越来越独立于 XSLT,拥有自己的生命。例如,几种 DOM 实现(包括 Microsoft 的)允许您使用 selectNodes(XPath) 等方法来选择 DOM 树结构中的节点,并且正在考虑将此类功能添加到下一版标准 DOM3 中。XPath 也用于其他 W3C 规范中,包括 XPointer 和 XQuery。

XPath 与 XSLT 的分离效果相当好,但也有一些地方的分离显得笨拙,而且在许多情况下很难知道应该阅读哪个文档来找到某个特定问题的答案。例如,XPath 表达式可以包含对变量的引用,但创建变量并为其赋予初始值是 XSLT 的工作。另一个例子:XPath 表达式可以调用函数,并且定义了一系列标准函数。那些效果完全独立(如 string-length())的函数在 XPath 规范中定义,而那些行为依赖于 XSLT 定义的附加函数(如 key())则在 XSLT 规范中定义。

由于这种分离方式笨拙,我编写本书时将 XSLT+XPath 视为一种单一语言。例如,所有标准函数都一起在第 7 章中描述。在参考部分,我试图指明每个函数或其他构造在原始标准中的定义位置,但基本假设是您同时使用这两种语言,而无需知道一个语言在哪里停止,另一个语言在哪里接手。这种方法的唯一缺点是,如果您想单独使用 XPath(例如在使用 DOM selectNodes() 方法时),您需要检查第 7 章中的函数描述,以确定它是 XPath 核心的一部分还是 XSLT 的附加功能。

XSLT 和 Internet Explorer 5

早在 1998 年 XSL 的第一个草案提案发布后不久,微软就发布了一个用于 IE4 的部分实现作为技术预览。随后,随着 IE5 的发布,它被一个相当不同的实现所取代。这个第二个实现,称为 MSXSL,基本上在现场保持不变,直到最近,它仍然与每个 IE5 和 IE5.5 版本一起提供,也与 Windows 2000 一起提供。不幸的是,微软操之过急,XSLT 标准发生了变化和发展,因此当 XSLT 1.0 版推荐最终于 1999 年 11 月 16 日发布时,它与最初的微软产品几乎没有相似之处。

推荐是 W3C 制作的最具决定性的文档。它在技术上并非标准,因为标准只能由政府批准的标准组织发布。但在本书中,我将经常将其笼统地称为“标准”。

许多差异,例如关键字的更改,非常表面化,但有些差异更深层;例如,等号运算符定义的更改。

因此,微软 IE5 方言的 XSL(我称之为 WD-xsl)也超出了本书的范围。请不要假设本书中的任何内容与原始微软 XSL 相关,因为即使语法看起来与 XSLT 相似,该构造的含义也可能完全不同。

您可以在 Wrox 出版的《XML IE5 程序员参考手册》(ISBN 1-861001-57-6)中找到有关 WD-xsl 的信息。

正如我们已经看到的,微软的 MSXML3 是 XSLT 1.0 规范的完整实现,但撰写本文时,您必须单独下载和安装它。MSXML3 实际上支持旧的 WD-xsl 方言和较新的 XSLT 1.0 语言;它根据 <xsl:stylesheet> 元素的命名空间 URI 来决定使用哪一个。

微软还发布了一个 转换器,用于将样式表从 WD-xsl 升级到 XSLT 1.0。然而,这并不是故事的结局,因为,当然,有数百万台安装的 IE5 仅支持旧版本。如果您想开发一个向浏览器提供 XML 并依赖浏览器解释其 XSLT 样式表的网站,那么您目前需要努力确保您的所有用户都能处理它。微软确实提供了一个 CAB 文件安装程序来帮助推广 MSXML3——有关详细信息,请查看 MSDN 网站。

如果您在服务器上使用微软技术,有一个名为 XSLISAPI 的 ISAPI 扩展,它允许您在浏览器中进行转换(如果支持),否则在服务器上进行。但是,除非您控制浏览器配置,否则在 ASP 页面或 Java Servlets 中驱动的 XML 到 HTML 的 **服务器端** 转换,对于严肃的项目来说,实际上是唯一的实用选择。

有关微软 XML 产品的信息可在附录 A 中找到——但请注意,这些信息很快就会过时。

XSLT 和 XML

XSLT 本质上是转换 XML 文档的工具。在本章开头,我们讨论了为什么这很重要,但现在我们需要更精确地了解两者之间的关系。XSLT 紧密交互的 XML 的两个特定方面是:XML 命名空间;另一个是 XML 信息集。这些将在以下各节中讨论。

XML 命名空间28

XSLT 的设计基于 XML 命名空间是 XML 标准的重要组成部分。因此,当 XSLT 标准提到 XML 文档时,它实际上是指*还符合 XML 命名空间规范*的 XML 文档,该规范可在 http://www.w3.org/TR/REC-xml-names 找到。

有关 XML 命名空间的完整解释,请参阅 Wrox Press 出版的《Professional XML》(ISBN 1-861003-11-0)第 7 章。

命名空间在 XSLT 中起着重要作用。它们的目的允许您在同一个 XML 文档中混合来自两个不同词汇表的标记。例如,在一个词汇表中,<table> 可能意味着二维值数组,而在另一个词汇表中,<table> 指的是一件家具。以下是它们如何工作的快速回顾:

  • 命名空间由唯一资源标识符 (URI) 标识。它可以采用多种形式。一种形式是我们熟悉的 URL,例如 http://www.wrox.com/namespace。另一种形式(尚未完全标准化,但在某些 XML 词汇表中已使用,例如 http://www.biztalk.org)是 URN,例如 urn:java:com.icl.saxon。URI 的详细形式并不重要,但选择一个唯一的 URI 是个好主意。一个好的方法是使用您自己网站的 URL。但不要因此认为网站上必须有什么东西可以指向该 URL。命名空间 URI 仅仅是一个您选择与其他人的命名空间 URI 不同的字符串;它不需要指向任何东西。
  • 由于命名空间 URI 通常很长并且使用“/”等特殊字符,因此它们不会在元素和属性名称的完整形式中使用。相反,文档中使用的每个命名空间都可以被赋予一个简短的昵称,而这个昵称被用作元素和属性名称的前缀。前缀的选择无关紧要,因为元素或属性的真实名称仅由其命名空间 URI 和局部名称(前缀后面的名称部分)决定。例如,我所有的示例都使用前缀 xsl 来引用命名空间 URI http://www.w3.org/1999/XSL/Transform,但只要您一致使用,也可以使用前缀 xslt。
  • 对于元素名称,您还可以声明一个默认命名空间 URI,该 URI 将与无前缀的元素名称相关联。然而,默认命名空间 URI 不适用于无前缀的属性名称。

命名空间前缀使用任何元素标签中的特殊伪属性声明,形式为:

xmlns:prefix = "namespace-URI"

这声明了一个命名空间前缀,该前缀可用于该元素的名称、其属性以及该元素中包含的任何元素或属性的名称。默认命名空间(用于没有前缀的元素,但不用于属性)使用伪属性类似地声明:

xmlns = "namespace-URI"

XSLT 不能用于处理不符合 XML 命名空间推荐的 XML 文档。在实践中,这不成问题,因为大多数人将 XML 命名空间视为 XML 标准的内在部分,而不是一个附加的可选功能。但这确实有一些影响。特别是,认真使用命名空间几乎与认真使用文档类型定义 (DTD) 不兼容,因为 DTD 不识别元素名称中前缀的特殊含义;因此,支持命名空间的后果是 XSLT 对 DTD 的支持非常少,而是等待其替代设施 XML Schema。

XML 信息集

XSLT 被设计用于处理 XML 文档携带的信息,而不是原始文档本身。这意味着,作为一名 XSLT 程序员,您会获得源文档的树状视图,其中某些方面可见,而其他方面不可见。例如,您可以看到属性名称和值,但您看不到属性是用单引号还是双引号写的,您看不到属性的顺序,您也无法判断它们是否写在同一行上。

一个令人困惑的细节是,人们曾多次尝试确切定义构成格式良好的 XML 文档的基本信息内容,而不是其偶然的标点符号。迄今为止的所有尝试都得到了略有不同的答案。提供 XML 文档内容通用词汇表的最新、最权威的尝试是 XML 信息集定义(通常称为“infoset”),可在 http://www.w3.org/TR/xml-infoset 找到。

不幸的是,这来得太晚,无法使所有标准保持一致。例如,有些将注释视为重要的,有些则不;有些将命名空间前缀的选择视为重要的,有些则认为它们无关紧要。我将在第 2 章中确切描述 XSLT(或更准确地说,XPath)如何定义 XML 的树模型,以及它在细节上与文档对象模型 (DOM) 等其他定义有何不同。

您将开始听到的一个专业术语是“Post-Schema-Validation Infoset”或 PSVI 的概念。它包含源文档的重要信息,并增加了从其 XML Schema 中获取的信息。因此,它允许您不仅找出属性值是“17.3”,而且还找出该属性在模式中被描述为非负十进制数。XSLT 尚无法使用此信息,但它在下一版本 XSLT 2.0 的已发布需求列表中占有重要地位。

XSL 和 CSS

为什么会有两种样式表语言,XSL(即 XSLT 加上 XSL 格式化对象)以及级联样式表(CSS 和 CSS2)?

公平地说,在一个理想的世界里,应该只有一种语言担任这个角色,之所以存在两种,是因为没有人能够发明出一种能够将 CSS 的简洁和经济(用于处理简单的事情)与 XSL 的强大(用于处理更复杂的事情)结合起来的东西。

CSS(我在此包含 CSS2,它极大地扩展了您控制页面最终外观的程度)主要用于呈现 HTML,但它也可以直接用于呈现 XML,通过定义每个 XML 元素的显示特征。然而,它有严重的局限性。它不能重新排序源文档中的元素,不能添加文本或图像,不能决定显示哪些元素以及省略哪些元素,不能计算总数或平均值或序列号。换句话说,它只能在源文档的结构已经非常接近最终显示形式时使用。

尽管如此,CSS 编写简单,而且机器资源消耗很少。它不重新排序文档,因此不需要在内存中构建文档的树形表示,并且可以在接收到第一个文本后立即开始显示文档。也许最重要的是,CSS 对 HTML 作者来说非常简单,无需任何编程技能。相比之下,XSLT 功能强大得多,但它消耗的内存和处理器资源也多得多,培训预算也相应增加。

通常适合一起使用这两种工具。使用 XSLT 创建一个接近最终形式的文档表示,即包含正确的文本和正确的顺序,然后使用 CSS 添加最后的润色,通过选择字体大小、颜色等。通常(如今)您会在服务器上进行 XSLT 处理,在客户端(浏览器)上进行 CSS 处理,因此这种方法的另一个优点是减少了通过线路发送的数据量,这应该会提高用户响应时间,并推迟下一次昂贵的带宽增长。

XSL 的历史

与大多数 XML 系列标准一样,XSLT 由万维网联盟 (W3C) 开发,这是一个由 Web 发明者 Tim Berners-Lee 组织的公司的联盟。有关 XSL 历史和样式提案的有趣页面可在 http://www.w3.org/Style/History/ 找到。

史前史

HTML 最初由 Berners-Lee 设计,作为一套标记逻辑文档结构的标签;标题、段落、链接、引用、代码段等等。很快人们想要更多地控制文档的外观,他们希望像处理印刷和纸张一样控制交付出版物的外观。因此,HTML 获得了越来越多的标签和属性来控制表示;字体、边距、表格、颜色,以及所有随之而来的内容。随着它的发展,出版的文档变得越来越依赖于浏览器,人们意识到最初的简单性和通用性目标正在逐渐丧失。

普遍认为解决办法是内容与表现分离。这不是一个新概念;它在 1980 年代开发标准通用标记语言 (SGML) 时得到了很好的发展,其架构又受到 ISO 开放文档架构 (ODA) 标准的详尽(且从未实现)工作的影响。

正如 XML 是从 SGML 的一个大大简化的子集派生出来的一样,XSLT 的起源也来自于一个名为 DSSSL(Document Style Semantics and Specification Language)的基于 SGML 的标准。DSSSL(我发音为 *Dissel*)主要是为了满足开发一种标准的与设备无关的语言来定义 SGML 文档的输出呈现的需求而开发的,特别是用于高质量的排版呈现。在 20 世纪 90 年代初 DSSSL 出现之前,SGML 已经存在了很长时间,但在此之前,输出端一直由专有的、通常非常昂贵的工具处理,这些工具旨在驱动同样昂贵的照相排版机,因此这项技术实际上只被大型出版商采用。

C. M. Sperberg-McQueen 和 Robert F. Goldstein 在 WWW '94 会议上发表了一篇题为《为万维网增加 SGML 智能的宣言》的有影响力的论文。您可以在以下网址找到它:http://www.ncsa.uiuc.edu/SDG/
IT94/Proceedings/Autools/sperberg-mcqueen/sperberg.html。

作者提出了一套样式表语言的要求,这很好地阐述了 XSL 设计者试图达到的目标。与当时的其他提案一样,单独的转换语言的概念尚未出现,该论文的很大一部分致力于语言的呈现能力。然而,有许多形成性的想法,包括用于处理当前环境中特定功能不可用的情况的回退处理的概念。

在此引用该论文的一些摘录是值得的:

理想情况下,样式表语言应该是声明式的,而不是过程式的,并且应该允许样式表充分利用 SGML 文档的结构。样式必须能够随着元素的结构位置而变化:笔记中的段落可能与正文中的段落格式不同。样式必须能够随着元素的属性值而变化:类型为“display”的引用可能需要与类型为“inline”的引用格式不同。它们甚至可能需要随着*其他*元素的属性值而变化:编号列表中的项目将看起来与项目符号列表中的项目不同。

同时,该语言必须易于以过程式方式解释:实现样式表语言不应成为实现 Web 客户端的主要挑战。

语义应该是累加的:用户应该能够通过向现有(可能标准)样式表添加新规范来创建新样式表。这不需要复制整个基础样式表;相反,用户应该能够在本地存储用户自己对标准样式表的更改,并在浏览时添加这些更改。这对于支持标准 DTD 的本地修改尤为重要。

在语法上,样式表语言必须非常简单,最好是易于解析。一个明显的可能性:将样式表语言表述为 SGML DTD,以便每个样式表都将是一个 SGML 文档。由于浏览器已经知道如何解析 SGML,因此无需额外的努力。

我们强烈建议使用 DSSSL 的一个子集来制定用于万维网的样式表;随着 DSSSL 标准工作的完成,社区没有理由从零开始发明自己的样式表语言。完整的 DSSSL 标准可能过于苛刻而无法完全实现,但即使事实证明如此,它也只为定义一个必须支持的 DSSSL 子集提供了论据,而不是为自制语言提供论据。与自制规范不同,DSSSL 的子集具有预定义的增长路径。我们预计将制定一个可用的、可实现的 DSSSL 子集用于 WWW 样式表,并邀请所有相关方加入此项工作。

1995 年末,W3C 赞助的样式表语言研讨会在巴黎举行。考虑到 James Clark 后来在 XSLT 推荐中担任编辑的角色,阅读他对 DSSSL 目标的贡献的记录很有趣,可以在 http://www.w3.org/Style/951106_Workshop/report1.html#clark 找到。

以下是从这些记录中选取的几段:

DSSSL 同时包含转换语言和格式化语言。最初需要转换才能实现某些类型的样式(例如目录)。查询语言现在负责这一点,但转换语言仍然存在,因为它本身很有用。

应可能实现简单和复杂的设计,样式应适用于批量格式化以及交互式应用程序。现有系统应能够仅通过最少的更改支持 DSSSL(显然需要一个 DSSSL 解析器)。

该语言严格声明式,这是通过采用 Scheme 的函数式子集来实现的。应可能实现交互式样式表编辑器。

DSSSL 样式表非常精确地描述了一个从 SGML 到流对象树的函数。它允许部分样式表组合(“级联”,如 CSS 中):某个规则可能基于隐式和显式优先级覆盖另一个规则,但冲突样式之间没有混合。33

James Clark 以一句评论结束了他的演讲:

创建一种良好、可扩展的样式语言是困难的!

人们怀疑编辑 XSLT 推荐的工作并没有让他改变主意。

第一个 XSL 提案

在这些早期讨论之后,W3C 建立了一个正式的活动来创建样式表语言提案。该组的职权范围规定,它应该基于 DSSSL。

作为这项活动的结果,出现了第一个正式的 XSL 提案,日期为 1997 年 8 月 21 日。它可以在 http://www.w3.org/TR/NOTE-XSL.html 找到。

列出了十一位作者。其中包括五位来自微软,三位来自 Inso Corporation,以及 ArborText 的 Paul Grosso、James Clark(他独立工作)和爱丁堡大学的 Henry Thompson。

描述语言目的的部分值得阅读:

XSL 是一种为 Web 界设计的样式表语言。它提供了超越 CSS 的功能(例如,元素重排)。我们期望 CSS 将用于显示结构简单的 XML 文档,而 XSL 将用于需要更强大格式化功能或用于格式化高度结构化的信息(如 XML 结构化数据或包含结构化数据的 XML 文档)的场合。

Web 作者在三个不同级别的复杂性下创建内容:

  •    标记:仅依赖于声明式语法
  •    脚本:此外,还使用“代码片段”来实现更复杂的行为
  •    程序:使用完整的编程语言

XSL 旨在通过为大多数数据描述和渲染需求提供声明式解决方案,从而使“标记”级别的用户能够轻松使用。不太常见的任务则通过优雅地切换到熟悉的脚本环境来满足。这种方法对 Web 发布社区来说很熟悉,因为它模仿了 HTML/JavaScript 环境。

XSL 提供的强大功能允许

  •    基于祖先/后代、位置和唯一性的源元素格式化
  •    创建格式化结构,包括生成的文本和图形
  •    定义可重用的格式化宏
  •    与书写方向无关的样式表
  •    可扩展的格式化对象集

作者随后仔细解释了他们为何认为有必要偏离 DSSSL,并描述了为何认为需要一个独立于 CSS(级联样式表)的语言。

然后,他们陈述了一些设计原则

  • XSL 应可直接在 Internet 上使用。

  • XSL 应以 XML 语法表示。

  • XSL 应提供一种声明式语言来完成所有常见的格式化任务。

  • XSL 应提供一个“转义”到脚本语言的机制,以满足更复杂的格式化任务,并实现可扩展性和完整性。

  • XSL 将是 DSSSL 的一个子集,并附带了拟议的修订。由于 XSL 不再是 DSSSL 的子集,他们巧妙地提议修订 DSSSL,使其成为 XSL 的超集。

  • 应能够将 CSS 样式表机械地映射到 XSL 样式表。

  • XSL 应借鉴 FOSI 样式表语言的用户体验。

  • XSL 中的可选功能数量应保持最少。

  • XSL 样式表应易于人类阅读且相对清晰。

  • XSL 设计应迅速完成。

  • XSL 样式表应易于创建。

  • XSL 标记的简洁性不太重要。

作为一个需求陈述,这算不上最好的。它读起来不像与用户交谈并了解他们需求时得到的那种列表。它更像是设计者在知道他们想要制作什么时写下的列表,包括一些政治上的妥协以应对可能提出异议的人。但如果你想了解 XSLT 为什么会变成现在的样子,这个列表无疑是思想的证据。

第一个提案中描述的语言包含了 XSLT 最终出现时的许多关键概念,但语法几乎认不出来。当时已经很清楚,该语言应基于模板,这些模板处理与定义模式匹配的源文档中的节点,并且该语言应无副作用,以便“渐进式渲染和处理大型文档”。我将在第 37 页更详细地探讨此要求的意义,并在第 9 章中讨论其对样式表设计方式的影响。基本思想是,如果一个样式表表示为一组完全独立的操作,每个操作除了从其输入生成输出的一部分之外没有外部影响(例如,它不能更新全局变量),那么当输入的特定部分发生变化时,就可以独立生成输出的任何部分。XSLT 语言是否真正实现了这一目标仍然是一个悬而未决的问题。

微软在这一提案出现五个月后,即 1998 年 1 月,发布了他们的第一个技术预览版。

为了让 W3C 评估该提案,Norman Walsh 制作了一份需求摘要,该摘要于 1998 年 5 月发布。可在 http://www.w3.org/TR/WD-XSLReq 找到。

他的论文大部分篇幅都用于列举该语言应支持的排版功能,这遵循了在此之前和之后,格式化方面的内容比转换方面的内容占更多篇幅的传统。但作为 XSLT 的爱好者,这不必让我们担心,因为标准的成功程度总是与其长度成反比。

Walsh 关于该语言转换方面的说法尤其简洁,尽管他显然有理由认为这些功能是必要的,但遗憾的是,他没有告诉我们他为什么包含这些而排除其他功能,例如排序、分组和汇总。

  • 祖先、子节点、同级节点、属性、内容、析取、否定、枚举、基于任意查询表达式的计算选择。

  • 算术表达式;算术、简单布尔比较、布尔逻辑、子字符串、字符串连接。

  • 数据类型:标量类型、度量单位、流对象、XML 对象。

  • 副作用:无全局副作用。

  • 标准过程:表达式语言应包含一组内置于 XSL 语言的过程。这些仍有待确定。

  • 用户定义函数:用于重用。可参数化,但不可递归。

在此活动之后,XSL 的第一个工作草案(不要与提案混淆)于 1998 年 8 月 18 日发布,语言开始成形,并逐渐趋向于 1999 年 11 月 16 日的最终推荐标准,尽管每个工作草案都进行了重大修改,但保留了最初的设计原则。

截至撰写本文时,XSLT 1.0 推荐标准仍是当前版本,也是大多数当前产品遵循的版本,尽管 XSLT 1.1 的工作草案于 2000 年 12 月 12 日发布。本书中包含了 XSLT 1.1 的新功能,因为它们已开始出现在一些产品中;但我已将其标记为 XSLT 1.1 功能,以警告您并非所有产品都具备这些功能。但在大多数情况下,这些功能基于许多供应商在其 XSLT 1.0 产品中提供的扩展,因此您很可能会找到类似的功能。

那么,现在让我们来看看 XSLT 作为一种语言的基本特征。

XSLT 作为一种语言

作为一种语言,XSLT 最显著的特征是什么,使它区别于其他语言?在本节中,我将挑选三个最引人注目的特征:它是用 XML 语法编写的,它是一种无副作用的语言,以及它的处理被描述为一组独立的模式匹配规则。

使用 XML 语法

正如我们所见,早在 1994 年就提出了使用 SGML 语法编写样式表,这个想法似乎逐渐成为公认的智慧。很难确切追溯其根本论据,而且当你发现自己写下类似的内容时,

<xsl:variable name="y">
   <xsl:call-template name="f">
      <xsl:with-param name="x"/>
   </xsl:call-template>
</xsl:variable>

来表达在其他语言中会写成“y=f(x);”的内容,那么你可能会想知道这样的决定是如何做出的。

事实上,情况本可以更糟:在非常早期的草案中,用于编写现在称为 XPath 表达式的语法也是用 XML 表示的,因此,而不是写 select="book/author/first-name",您必须写类似以下内容:

<select>
   <path>
      <element type="book">
      <element type="author">
      <element type="first-name">
   </path>
</select>

将 XSLT 样式表用 XML 表示的最明显的论据可能是:

  • 浏览器中已存在 XML 解析器,因此如果可以重复使用它,可以减小体积。
  • 每个人都厌倦了 HTML/XML 和 CSS 之间的语法不一致,并且不希望同样的事情再次发生。

  • DSSSL 的 Lisp 风格语法被广泛认为是其采用的障碍;最好使用目标社区已熟悉的语法。

  • 许多现有的流行模板语言(包括简单的 ASP 和 JSP 页面)都表示为输出文档的轮廓,其中嵌入了指令,因此这是一个熟悉的概念。

  • 所有词法设备都是可重用的,例如 Unicode 支持、字符和实体引用、空白处理、命名空间。

  • 偶尔,将样式表作为转换的输入或输出很有用(例如微软的 XSL 转换器),因此如果样式表能够读取和写入其他样式表,那将是一个好处。

  • 提供可视化开发工具可以轻松解决必须输入大量尖括号的不便。(此类工具已开始可用,并且我在附录 E 中描述了一些。)

无论您是否喜欢,基于 XML 的语法现在都是该语言的固有特征,它既有优点也有缺点。它确实需要大量键入,但最终,击键次数对解决特定转换问题的难易程度几乎没有影响。

无副作用

XSL 应是一种无副作用的声明式语言的理念在早期关于语言目标和设计原则的陈述中反复出现,但似乎没有人解释为什么:用户将从中获得什么好处?

编程语言中的函数或过程如果会更改其环境,则称为具有副作用;例如,如果它可以更新另一个函数或过程可以读取的全局变量,或者它可以将消息写入日志文件,或者提示用户。如果函数有副作用,那么按正确的次数以正确的顺序调用它们就很重要。没有副作用的函数(有时称为纯函数)可以被调用任意次数,并以任意顺序调用。计算三角形面积多少次都不会改变结果;但如果计算面积的函数有改变三角形大小的副作用,或者您不知道它是否有副作用,那么只调用一次就很重要。

我在第 9 章关于计算样式表的部分(第 608 页)中对此概念进行了更详细的阐述。

在“该语言应同样适用于批处理或交互式使用”以及“该语言应能够渐进式渲染”的陈述中,可以找到对此为何被认为可取的提示。有一个担忧是,当您下载大型 XML 文档时,在从服务器接收到最后一个字节之前,您将无法在屏幕上看到任何内容。同样,如果对 XML 文档进行了小的更改,那么能够确定屏幕显示所需的更改,而不必从头开始重新计算整个内容,那将是很好的。如果一种语言有副作用,那么必须定义语言中语句的执行顺序,否则最终结果将是不可预测的。没有副作用,语句可以按任何顺序执行,这意味着原则上可以有选择地、独立地处理样式表的各个部分。

XSLT 是否真正实现了这些目标尚有争议。当然,考虑到语言中允许的表达式和模式的灵活性,确定输入文档的一个部分的一个小更改会影响输出文档的哪些部分并不容易。同样,所有现有的 XSLT 处理器都要求将整个文档加载到内存中。然而,期望过高是不明智的。E. F. Codd 在 1970 年发布关系演算时,声称声明式语言是可取的,因为它可以进行优化,而当时使用的导航式数据访问语言则不能。事实上,直到十五年后,关系优化技术(并且,公平地说,硬件价格)才达到大型关系数据库在商业上可行的程度。但最终他被证明是正确的,希望同样的原则最终也能在转换和样式化语言领域带来类似的益处。

当然,总会有一些转换需要在使用任何输出之前提供整个文档;例如,样式表对数据进行排序,或者从目录开始。但还有许多其他转换,输出的顺序直接反映了输入的顺序,在这种情况下可以进行渐进式渲染。截至撰写本文时,我们开始看到实现者利用此功能的第一批迹象:例如,Xalan-Java 2 运行一个转换线程与解析线程并行,因此转换器可以在解析器完成之前生成输出,并且 MSXML3(从其 API 来看)似乎基于类似的原理。Stylus Studio 调试工具(在附录 E 中描述)会跟踪输出文档的各个部分与用于生成它们的模板规则之间的依赖关系,因此可以看到选择性地重新生成输出的潜力,当发生小的更改时。

在实践中,无副作用意味着您无法更改变量的值。您可能会觉得这种限制一开始非常令人沮丧,并且是为这些相当遥远的好处付出的巨大代价。但随着您熟悉该语言并学会如何按其设计方式使用它,而不是按照您从其他语言熟悉的方式使用它,您会发现自己不再将其视为限制。事实上,其中一个好处是它消除了您代码中的一整类错误!我将在第 9 章回到这个主题,在那里我将概述 XSLT 样式表的一些常见设计模式,特别是描述如何使用递归代码来处理过去您可能会使用可更新变量来跟踪当前状态的情况。

基于规则

典型的 XSLT 样式表的主要特征是它由一系列模板规则组成,每个规则描述如何处理特定元素类型或其他构造。规则的排列顺序无关紧要;它们不必匹配输入顺序或输出顺序,事实上,几乎没有什么线索表明样式表作者期望在源文档中遇到哪种顺序或嵌套的元素。正是这一点使 XSLT 成为一种声明式语言,因为您指定在输入中出现特定模式时应生成什么输出,这与过程式程序不同,后者您必须指定要执行的任务以及它们的顺序。

这种基于规则的结构非常像 CSS,但有一个主要区别,即模式(描述规则适用于哪些节点)和动作(描述规则匹配时发生的事情)在功能上都更丰富。

示例:显示一首诗

让我们看看如何使用基于规则的方法来格式化一首诗。同样,我们还没有介绍所有概念,所以我不会试图解释其工作原理的每个细节,但看看模板规则在实践中实际是什么样子很有用。

输入

让我们以这首诗作为我们的 XML 源。源文件名为 poem.xml,样式表名为 poem.xsl。

<poem>
   <author>Rupert Brooke</author>
   <date>1912</date>
   <title>Song</title>
  <stanza>
      <line>And suddenly the wind comes soft,</line>
      <line>And Spring is here again;</line>
      <line>And the hawthorn quickens with buds of green</line>
      <line>And my heart with buds of pain.</line>
   </stanza>
   <stanza>
      <line>My heart all Winter lay so numb,</line>
      <line>The earth so dead and frore,</line>
      <line>That I never thought the Spring would come again</line>
      <line>Or my heart wake any more.</line>
   </stanza>
   <stanza>
      <line>But Winter's broken and earth has woken,</line>
      <line>And the small birds cry again;</line>
      <line>And the hawthorn hedge puts forth its buds,</line>
      <line>And my heart puts forth its pain.</line>
   </stanza>
</poem>

输出

我们将编写一个样式表,以便此文档在浏览器中显示如下:

样式表

它以标准头部开始。

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">

现在我们将为源文档中的每种元素类型编写一个模板规则。<poem> 元素的规则创建 HTML 输出的骨架,定义输出中元素的顺序(不一定与输入顺序相同)。<xsl:value-of>指令将选定元素的值插入到输出的该点。<xsl:apply-templates>指令导致选定的子元素被处理,每个子元素都使用自己的模板规则。

<xsl:template match="poem">
   <html>
   <head>
      <title><xsl:value-of select="title"/></title>
   </head>
<body>
      <xsl:apply-templates select="title"/>
      <xsl:apply-templates select="author"/>
      <xsl:apply-templates select="stanza"/>
      <xsl:apply-templates select="date"/>
   </body>
   </html>
</xsl:template>

<title>、<author>和<date>元素的模板规则非常简单:它们获取元素的内容(由“select='.'”表示),并在适当的 HTML 标签中将其包围,以定义其显示样式。

<xsl:template match="title">
   <div align="center"><h1><xsl:value-of select="."/></h1></div>
</xsl:template>
<xsl:template match="author">
   <div align="center"><h2>By <xsl:value-of select="."/></h2></div>
</xsl:template>
<xsl:template match="date">
   <p><i><xsl:value-of select="."/></i></p>
</xsl:template>

<stanza>元素的模板规则将每个诗节放入一个 HTML 段落中,然后调用处理诗节内行的处理,如行模板规则所定义的。

<xsl:template match="stanza">
  <p><xsl:apply-templates select="line"/></p>
</xsl:template>

<line>元素的规则稍微复杂一些:如果行在诗节内的位置是偶数,它会在行前面加上两个不间断空格字符(&#160;)。<xsl:if>指令测试一个布尔条件,该条件在这种情况下调用 position() 函数来确定当前行的相对位置。然后输出该行的内容,后跟一个空的 HTML <br> 元素来结束该行。

<xsl:template match="line">
   <xsl:if test="position() mod 2 = 0">&#160;&#160;</xsl:if>
   <xsl:value-of select="."/><br/>
</xsl:template>

最后,我们关闭 <xsl:stylesheet> 元素。

</xsl:stylesheet>

虽然模板规则是 XSLT 语言的一个特征,但我们将看到这并非编写样式表的唯一方法。在第 9 章中,我将描述四种不同的 XSLT 样式表设计模式,其中只有一种大量使用模板规则。事实上,我本章早些时候提供的“Hello World”样式表并没有真正使用模板规则:它属于我称之为填空的设计模式,因为样式表基本上包含输出的固定部分,其中嵌入了指令,说明从何处获取数据填入变量部分。

XSLT 1.0 之后

我讨论了 XSLT 1.0 的来源,但它将走向何方?

XSLT 1.0 发布后,负责该语言的 XSL 工作组决定将增强需求分为两类:XSLT 1.1 将标准化少数紧迫的功能,这些功能已被供应商作为扩展添加到他们的产品中;XSLT 2.0 将处理需要进一步研究的更具战略性的需求。

XSLT 1.1

XSLT 1.1 的工作草案于 2000 年 12 月 12 日发布。它描述了对 XSLT 1.0 规范的四项增强。

  • 多个输出文档:一个<xsl:document>指令,模仿了 Saxon 最初提供的扩展,以及随后在 xt、Xalan 和 Oracle 等其他产品中提供的扩展,允许将源文档拆分成多个输出文档。(所有这些产品都在本书的附录中进行了描述。)

  • 临时树:能够将一个处理阶段创建的树作为后续处理阶段的输入。这项增强功能模仿了 xt 中首先引入并随后在 xt、Xalan 和 Oracle 等其他产品中复制的 node-set() 扩展函数。

  • 与用 Java 和 ECMAScript 编写的扩展函数进行标准绑定。XSLT 1.0 允许样式表调用外部函数,但没有说明如何编写这些函数,结果是为 Xalan 编写的扩展函数无法与 xt 或 Saxon 一起使用,反之亦然。XSLT 1.1 定义了一个用于绑定用任何语言编写的扩展函数的通用框架,并为 Java 和 ECMAScript(JavaScript 的官方名称)提供了特定的映射。

  • 支持 xml:base 构造,这是 XML 核心标准的一个后期添加,它允许 XML 文档指定用于解析文档中包含的任何相对 URI 的基本 URI。

截至撰写本文时,XSLT 1.1 仍是一个工作草案,并且没有官方声明何时可能最终定稿。有人建议,在冻结 XSLT 1.1 规范之前,更深入地探讨 XSLT 2.0 需求的影响将是一个好主意,以避免限制 XSLT 2.0 需求的满足方式。还可以推测,一些供应商认为市场才刚刚开始接受 XSLT 1.0,而实际上
用户更想要稳定性而不是增强功能。

尽管如此,我们还是决定继续在本书中包含 XSLT 1.1 功能的定义。这样,我们就进行了一次经过计算的赌博,即该规范将以与其发布草案非常相似的形式获得批准,并且将在今年(2001 年)得到产品的实现——有迹象表明这种情况已经开始发生。同时,我们已仔细标记了 XSLT 1.1 的增强功能,以便您可以将本书中的规范与最新的 W3C 推荐标准以及您选择的产品提供的功能进行核对,然后再使用它们。

截至我们付印时,W3C 已决定 XSLT 1.1 将不再进展到工作草案阶段,而是将作为开发 XSLT 2(见下页)的基础。

在本书中,“XSLT 1.1 工作草案”指的是 2000 年 12 月 12 日的草案。

XSLT 2.0 和 XPath 2.0

W3C XSL 工作组与工作组紧密合作,于 2001 年 2 月 14 日发布了 XSLT 2.0 和 XPath 2.0 的需求;您可以在以下 URL 找到文档:

http://www.w3.org/TR/xslt20req

http://www.w3.org/TR/xpath20req

W3C 工作组发布需求文档的原因是为了尝试将用户输入纳入标准化过程,因此将这些拟议增强功能列表视为最终决定是错误的。尽管如此,它们很好地表明了想法。总的来说,需求分为三类:

  • 明显缺失于当前标准中的功能,它们将使用户的生活大大简化;例如,用于分组相关节点的功能、额外的字符串处理和数值函数,以及读取文本文件以及 XML 文档的能力。

  • 添加 XML 查询工作组开发的功能。XQuery 是一种类似于 SQL 的语言规范,用于查询 XML 文档集合并以 XML 文档的形式返回结果。第一个公共工作草案于 2001 年 2 月 15 日发布(参见 http://www.w3.org/TR/2001/WD-xquery-20010215/),但它基于许多先前提案中的想法,特别是 Don Chamberlin、Jonathan Robie 和 Daniela Florescu 的作品,名为 Quilt 的语言。尽管 XQuery 是为在不同场景中使用而设计的,但它与 XSLT 和 XPath 之间存在许多功能上的重叠。W3C 希望保持其不同标准的一致性,并且拟议的 XQuery 规范中有许多功能可以有效地添加到 XPath 规范中,以使它们保持同步。这涉及双方的巨大妥协,因为 XML 查询组已确定的一些改进在理论上看起来很棒,但很难逆向安装到已广泛使用的语言中。

  • 用于利用和集成 XML Schema 的功能。W3C XML Schema 规范目前已进入高级阶段(于 2000 年 10 月 20 日成为候选推荐),并且在产品中已开始出现实现。该模式充当 DTD 的替代品,提供了一种更丰富的方式来指定文档中可能出现的元素和属性的数据类型。想法是,如果模式指定某个元素包含数字或日期(例如),那么在样式表中比较或对日期进行排序时,应该能够利用这些知识。在不彻底颠覆当前 XPath 语言(目前它是一种非常松散类型的语言)的情况下实现这一点将是一个重大挑战,因此仅凭这一点,我认为 XPath 2.0 的开发可能会花费相当长的时间。

在哪里使用 XSLT

在本章的最后一部分,我将尝试确定 XSLT 擅长处理哪些任务,从而也暗示哪些任务更适合使用其他工具。我还会探讨在应用程序的整体架构中使用 XSLT 的其他方法。

广义上讲,正如我在本章开头所讨论的,使用 XSLT 转换主要有两种场景:数据转换和发布;我们将分别考虑它们。

数据转换应用程序

仅仅因为 XML 的出现,数据转换也不会消失。即使越来越多的组织之间或组织内部应用程序之间的数据传输很可能使用 XML 进行编码,但仍然存在不同的数据模型、表示相同事物的不同方式,以及对不同的人来说有不同信息子集(回想一下本章开头,我们将音乐转换为不同的 XML 表示和不同的演示格式)。因此,无论我们对 XML 多么热情,现实情况是,逗号分隔值文件、EDI 消息以及其他任何格式在很长一段时间内仍将大量使用。

当您需要将一个 XML 数据集转换为另一个 XML 数据集时,XSLT 是一个显而易见的选择。

它可以用于选择性地提取数据、重新排序、将属性转换为元素或反之,以及进行许多类似的任务。它也可以简单地用于验证数据。作为一种语言,XSLT 最擅长操作信息结构,而不是内容;它是一种将行转换为列的好语言,但对于字符串处理(例如删除方括号之间的任何文本),与支持正则表达式的 JavaScript 或 Perl 等语言相比,它相当繁琐。但是,您始终可以通过在样式表中调用用其他语言(如 Java 或 Javascript)编写的过程来解决这些问题。

XSLT 对于将 XML 数据转换为任何基于文本的格式(如逗号分隔值或各种 EDI 消息格式)也很有用。文本输出实际上就像没有标签的 XML 输出,因此这不会给语言带来任何特殊问题。

更令人惊讶的是,XSLT 经常可以用于将非 XML 格式转换为 XML 或其他格式。

在这种情况下,您需要编写一种能够理解输入格式的解析器;但无论如何您都必须这样做。好处是,一旦您编写了解析器,其余的数据转换就可以用高级语言表示。这种分离也增加了您下次需要处理特定输入格式时能够重用解析器的机会。我将在第 10 章,第 656 页举例说明,其中输入是一种相当老式且明显非 XML 的格式,广泛用于家谱软件包之间交换数据。事实证明,即使在使用 XSLT 样式表处理它之前,也不必将数据写成 XML:您所需要做的就是让您的解析器看起来像 XML 解析器,让它实现标准的解析器接口之一:SAX 或 DOM。大多数 XSLT 处理器都会接受实现 SAX 或 DOM 接口的程序的输入,即使数据从未以 XML 的形式显示出来。

关于数据转换应用程序的一个注意事项:当今的所有 XSLT 处理器在转换过程中都依赖于将所有数据保存在内存中。内存中的树结构的大小可能是原始数据大小的十倍,因此实际上,XSLT 转换的数据大小限制是几兆字节。即使在这种规模下,复杂的转换也可能非常耗时,这在很大程度上取决于您实际想做的处理。

一种绕过此问题的方法是将数据分成块并分别转换每个块。
——当然,假设输入块和输出块之间存在某种对应关系。但当这种情况变得复杂时,就会出现 XSLT 不再是最佳工具的时候。例如,您可能最好将数据加载到关系数据库或对象数据库中,并使用数据库查询语言以不同的顺序再次提取它。

如果您需要串行处理大量数据,例如从零售交易日志中提取选定的记录,那么使用 SAX 接口编写的应用程序可能比等效的 XSLT 样式表花费更长的时间来编写,但它很可能运行得快得多。在许多情况下,使用 SAX 过滤器应用程序进行简单数据提取,然后使用 XSLT 样式表进行更复杂的处理,可能是在这种情况下最好的解决方案。

出版

数据转换和出版的区别在于,前者的数据是为另一个软件的输入而设计的,而后者的数据是为人类阅读(您希望)而设计的。此处的出版不仅意味着华丽的文本和多媒体,还意味着数据;从传统的制作和分发报告以便经理们了解业务状况的活动,到为客户制作在线电话账单和银行对账单,以及为公众制作火车时刻表。XML 对于此类数据出版应用程序以及更传统的文本出版(这是 SGML 的原始领地)非常理想。XML 被设计用于将信息与演示方式分开,这有时会使人们陷入使用 XML 进行演示细节是一种错误的想法。远非如此:如果您今天要设计一种下载字体到打印机的新格式,您可能会基于 XML 来设计。演示细节与任何其他类型的信息一样,都有权用 XML 进行编码。因此,我们可以看到 XSLT 在出版过程中的作用是将其转换为数据-带演示,其中两者至少原则上都是 XML 格式。

当今出版信息有两个重要的载体:打印纸张和网络。纸质印刷场景更为困难,因为用户对视觉质量有很高的期望。XSL 格式化对象试图定义一个基于 XML 的打印文件模型,用于在纸张或屏幕上进行高质量显示。由于要实现这一目标所需的参数数量庞大,该标准花费了很长时间才完成,并且可能需要更长的时间才能完全实现。但网络是一个要求较低的环境,在那里我们只需要将数据转换为 HTML,然后让浏览器尽最大努力在可用的显示器上进行处理。HTML 当然不是 XML,但它足够接近,因此可以进行简单的映射。将 XML 转换为 HTML 是当今 XSLT 最常见的应用。它实际上是一个两阶段过程:首先转换为在结构上等同于目标 HTML 的基于 XML 的模型,然后将其序列化为 HTML 标记而不是严格的 XML。

XHTML 1.0 的出现当然进一步简化了这个过程,因为

它是一种纯 XML 格式,但 XHTML 的普及速度还有待观察。
有待
观察。

何时进行转换?

向用户发布信息的流程在下图所示。

在此类系统中,有几个点 XSLT 转换可能适用。

  • 作者使用他们喜欢的工具或定制的表单填写界面输入的信息,可以转换为 XML 并在内容存储中以该形式存储。

  • 来自其他系统的 XML 信息可能会转换为另一种 XML 格式以存储在内容存储中。例如,它可能被分解成页面大小的块。

  • 用户请求页面时,XML 可以在服务器端转换为 HTML。可以使用 Java Servlet 或 Java Server Pages 等技术来控制这一点。在 Microsoft 服务器上,您可以使用微软 XML(http://msdn.microsoft.com/xml)提供的 XSL ISAPI 扩展,或者如果您需要更多应用程序控制,您可以在 ASP 页面上从脚本调用转换。

  • XML 可以发送到客户端系统,并在浏览器内转换为 HTML。这可以提供高度交互式的信息呈现,并减轻服务器的许多处理负担,但这取决于所有用户都拥有能够完成此任务的浏览器。

  • XML 数据也可以在发布时转换为其最终显示形式,并作为 HTML 存储在内容存储中。这最大限度地减少了显示时所需的工作量,并且对于呈现相同显示页面的许多用户来说是理想的选择。

没有一个正确的答案,通常多种技术的组合可能是合适的。一旦 XSLT 在浏览器中得到广泛支持,浏览器内的转换就具有吸引力,但这仍有很长的路要走。即使这样,仍然可能需要一些服务器端处理来以可管理的数据块的形式交付 XML,并保护安全信息。在服务器上进行交付时转换是一种流行的选择,因为它允许个性化,但对于流量高的网站来说,它可能是一个沉重的开销。一些繁忙的网站发现,提前为目标受众的每个部分生成不同的一组 HTML 页面,并在页面请求时仅选择正确的预构建 HTML 页面会更有效。

摘要

本章介绍性章节描述了 XSLT 的原因和去向。它试图回答以下问题:

  • 它是什么样的语言?

  • 它在 XML 系列中扮演什么角色?

  • 它从何而来,为什么它的设计方式如此?

  • 它应该在哪里使用?

您现在知道 XSLT 是一种声明式高级语言,用于转换 XML 文档的结构;它有两个主要应用:数据转换和演示;并且它可以在应用程序体系结构的多个不同点使用,包括数据捕获时、服务器交付时和浏览器显示时。您也对 XSLT 为什么会发展成今天的样子有了一定的了解。

现在是时候深入了解语言本身,看看它是如何完成这项工作的。在下一章中,我们将通过将输入和输出视为树结构,并使用模式来匹配输入树中的特定节点并定义何时匹配模式应向结果树添加哪些节点来研究转换是如何进行的。

版权所有 © 2000 Wrox Press Ltd
在浏览器中转换为 HTML。这可以提供高度交互式的信息呈现,并减轻服务器的许多处理负担,但这取决于所有用户都拥有能够完成此任务的浏览器。

  • XML 数据也可以在发布时转换为其最终显示形式,并作为 HTML 存储在内容存储中。这最大限度地减少了显示时所需的工作量,并且对于呈现相同显示页面的许多用户来说是理想的选择。

    没有一个正确的答案,通常多种技术的组合可能是合适的。一旦 XSLT 在浏览器中得到广泛支持,浏览器内的转换就具有吸引力,但这仍有很长的路要走。即使这样,仍然可能需要一些服务器端处理来以可管理的数据块的形式交付 XML,并保护安全信息。在服务器上进行交付时转换是一种流行的选择,因为它允许个性化,但对于流量高的网站来说,它可能是一个沉重的开销。一些繁忙的网站发现,提前为目标受众的每个部分生成不同的一组 HTML 页面,并在页面请求时仅选择正确的预构建 HTML 页面会更有效。

    摘要

    本章介绍性章节描述了 XSLT 的原因和去向。它试图回答以下问题:

    • 它是什么样的语言?

    • 它在 XML 系列中扮演什么角色?

    • 它从何而来,为什么它的设计方式如此?

    • 它应该在哪里使用?

    您现在知道 XSLT 是一种声明式高级语言,用于转换 XML 文档的结构;它有两个主要应用:数据转换和演示;并且它可以在应用程序体系结构的多个不同点使用,包括数据捕获时、服务器交付时和浏览器显示时。您也对 XSLT 为什么会发展成今天的样子有了一定的了解。

    现在是时候深入了解语言本身,看看它是如何完成这项工作的。在下一章中,我们将通过将输入和输出视为树结构,并使用模式来匹配输入树中的特定节点并定义何时匹配模式应向结果树添加哪些节点来研究转换是如何进行的。

    版权所有 © 2000 Wrox Press Ltd
  • © . All rights reserved.