在两部分组成的关于 XSLT 的系列文章的第一期中,介绍了 XSLT 2.0 的一些新特性,并说明了如何从抽象数据模型生成代码。为了示范这一过程,我建立了项目,开发一个健壮的代码生成器,为数据库服务器生成 SQL,并为 Web 服务器生成用于访问数据库的 PHP。我使用多层转换通过 XSL 构建 SQL。首先将抽象模型转化成数据库物理模式模型,然后使用该模式模型构建 SQL 代码。
接下来就要构建代码模型并从这个模型生成 PHP。在结束项目时,您将拥有系统的抽象模型、构建数据库的 SQL 代码和用于每个表的 PHP 包装器。但是在深入讨论 PHP 生成之前,我想首先回顾一下影响 XSL 模板设计及使用的 XSL 和 XSLT 2.0 的新特性。
对 XSL 模板的增强
要生成成功的代码则需要对目标语言(这里是 PHP)和代码生成语言(该例中即 XSLT)有充分的了解。第 1 部分的重点放在代码生成的基本原理上。本文对代码生成等式中的 XSL 一端进行了更深入的分析。
从本质上说,XSLT 是一种模板化的语言。它接受 XML 作为输入,然后使用一组模板将 XML 转化成 XML、HTML 或文本。生成器是相关模板的集合,使用两种模式 —— XML 模式和 Text 模式 —— 将原来输入的 XML 转化成代码。位于抽象模型和代码模板之间的中间模型使用 XML 模式,生成 PHP 和 SQL 的代码模板则使用文本模式。
这个代码生成系统使用 Saxon XSLT 引擎和一组自定义模板。为了方便起见,这些模板和输入放在同一个目录中。模板输出分别放到 PHP 和 SQL 代码目录中。不需要对 Saxon 作专门的扩展,虽然如果发现基本安装所提供的 XSL 标签或 XPath 函数不敷使用,那么可以用 Java? 扩展模板引擎。
XSL 模板的入口是与输入 XML 的根节点匹配的 XSL 模板。在 XSL 引擎启动时,它将输入 XML 应用于模板库。如果有与根节点(/)匹配的特殊模板,则首先执行它。下面是生成器中的主模板标签:
<xsl:template match="/">
这个匹配系统很重要,因为 XSL 要查看应用于当前正在处理节点的可用模板的列表,然后应用最匹配的模板。看一下清单 1 中的代码,这是上一期文章中的一个例子。
清单 1. 带有模式类型的模板
<xsl:template match="create" mode="sql">
DROP TABLE IF EXISTS <xsl:value-of select="@name" />;
CREATE <xsl:value-of select="@name" /> (
<xsl:apply-templates mode="sql" select="field" />
PRIMARY KEY ( <xsl:value-of select="@primary-key" /> )
);
</xsl:template>
代码告诉 XSL 这个模板应用于 create 标签。因此,当 XSL 遇到 create 标签时,它就会执行该模板。此外,还要注意该模板指定了模式。需要像清单 2 那样在 xsl:apply-templates 标签中指定模式。
清单 2. 应用模板的标签
<xsl:apply-templates mode="sql" select="$sql-model/sql" />
XSL 中的模式
模式是 XSL 的一个重要概念。因为内存中可能同时有多个 XML 分层结构,需要有一种方法对特定分层结构应用一组特殊的模板,或者可用于单个 XML 源的一组转换。于是就引入了模式。这个代码生成器中有一组模板以 PHP 作为模式,另一组则用 SQL 作为模式。通过使用模式将这两种语言的模板逻辑区分开来。
xsl:apply-templates 标签告诉 XSL 将可以用的模板应用于 XML 模型中 select 标签所指定的那一部分。此外,还规定了模式 sql,因此 XSL 只寻找那些采用 sql 模式的模板。这是一种方便的模板名称空间机制。