内容


使用 XML

XSLT 2.0 和 XQuery 对比

XPath 用于不同任务的两种语支

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 使用 XML

敬请期待该系列的后续内容。

此内容是该系列的一部分:使用 XML

敬请期待该系列的后续内容。

正在进行的标准化

自从 1999 年 11 月面世以来,我发现 XSLT(XSL 转换语言)是可用于操作 XML 文档的最有用的工具之一。许多可用的 API 和工具在 Java 或其他语言中使用 XML 文档,而且我在不同项目中使用了许多 XML 文档,但想不起有哪个 XML 项目不使用一点 XSLT 了。

那么我对 XSLT 2.0 开发有浓厚的兴趣就不足为奇了。XSLT 是功能强大的语言,它高级到甚至可以处理最复杂的操作,但它也非常冗长,以至于调试和维护大型样式表非常困难。W3C 希望解决这个问题和其他问题,所以将要发布两种语言:XSLT 2.0 和 XQuery 1.0。本文对这两种即将面世的语言进行比较,并提供了一些有关如何有效利用这两种语言的指导。

在撰写本文时,XSLT 2.0 和 XQuery 1.0 还处于 Candidate Release 状态,该状态是 W3C 用于不久要采用的标准的行话。多久?这取决于审查过程。

大量重叠

在设计上,XSLT 2.0 和 XQuery 1.0 有许多共同点。两种语言都基于同一基础:XPath 2.0。两种语言都专用于操作 XML 文档。两种语言都借用脚本 概念,即对简单任务使用解释语言。实际上,可以使用其中任一语言达到给定目的。两者功能相当。但是,每种语言都有不同的个性,我觉得,取决于要进行的任务,也可能取决于您的个性,您可能会更喜欢使用其中的一个,所以两个都值得学习一下。

下文将简单介绍两种语言的共同点和各自的特点,以便您选择适合自己的风格和正在进行的任务的一种语言。

XPath 基础

首先介绍 XPath 2.0。XSLT 由两种语言打包而成:XPath 语言和 XSLT 本身。XPath 是用于查询元素的语言,例如,选择属性或指定模板匹配(XSLT 中的匹配属性)时。XSLT 语言是用于指定转换结果的语言,指令包括 xsl:apply-templatesxsl:value-ofxsl:for-each 等。

考虑 清单 1 中的 XSLT 模板。它混合了一些 XPath 语言(matchselect 属性)、来自 XSLT 本身的元素(模板和 xsl:value-of 指令)和来自结果语言的元素(htmlhead):

清单 1. XSLT 模板
<xsl:template match="rss">
   <html>
      <head><title><xsl:value-of select="channel/title"/></title></head>
      <xsl:apply-templates/>
   </html>
</xsl:template>

XPath 和 XSLT 之间的任务分离并不新奇,但因为没有其他语言是基于 XPath 的,因此在 XQuery 出现以前,二者主要是理论区别。

XPath 2.0 是重要升级

XPath 2.0 是非常重要的升级。XPath 1.0 只能查询 XML 文档中的节点。XPath 2.0 可以操作序列,而序列可以包含节点(所以不会丢失任何内容)以及字符串、整数和其他原子值。差别虽细小但很重要:现在可以通过第二次查询提炼查询结果。以前在 XSLT 1.0 中,链接两个查询需要专用的功能。

另一个重要的更改是 XPath 2.0 支持循环和变量。换句话说,您可以在 XPath 中声明变量并从 XPath 中为其赋值。同样地对于循环,您可以在 XPath 中运行循环以计算返回值,例如,在处理发票行时用数量乘以价值。仍可以在 XSLT 中声明变量,XSLT 中的循环功能也有所增强。在升级中包装了许多强大功能!

新选项极大地简化了 XSLT 样式表。在 XSLT 1.0 中,必须编写许多算法,甚至递归编写简单算法。例如,计算发票总计时通常都需要递归算法。但在 XSLT 2.0 中再也不必如此了,这大大归功于 XPath 2.0 中的新功能。

XQuery 与 XSLT

XSLT 样式表可用于任何 XML 操作。就我个人而言,我曾使用 XSLT 进行网站发布、编译报告、计算统计、预处理 XML 文件,转换不同词汇或软件、准备导入数据库中的数据、处理数据库导出,甚至响应 Web 服务请求。

实际上,这是滥用语言。当然它能工作,但有时候最终的结果是与语言对抗。得到的样式表有太多递归函数,难以调试。

顾名思义,问题在于 XSLT 设计用于转换文档以发布,而非其他目的。XSLT 旨在作为一种通用查询语言,尽管它总是在没有更好选择的情况下被使用。与此相反,XQuery 设计用于查询文档和准备报告。

不同风味

不可否认,转换查询 是涵盖许多应用的通用词。已经介绍过,两种语言能力相当,因为它们都基于 XPath 2.0。但它们强调不同的用法模式,从而使其适用于不同的任务。

XSLT 的设计者假设您有意于处理大部分文档,这种假设在发布时是合理的。因此 XSLT 具有内置的遍历引擎,在默认情况下会处理整个文档。他们还假设您通常使用文本信息,因此 XSLT 不是一种强类型语言,最后,他们还假设您将以标记语言生成文档,因此 XSLT 编写为 XML 词汇。

XQuery 的设计者作了不同的假设。他们假设您在运行查询时希望将范围缩小到文档的一些章节,所以他们围绕 XPath 查询构建该语言。XQuery 没有默认行为,一切由您主宰。

他们还假设您使用有类型的数据,比如数据库抽象,而 XQuery 是强类型语言。最后,语法绝对不是 XML。

示例

为了阐明 XSLT 2.0 和 XQuery 1.0 之间的差异,我们来看一个示例。

为了比较两种语言,人们通常用两种语言编写同一个算法,但在特殊情况下,这样并不公平。因为每种语言都是在其他语言表现不佳的任务中表现良好,所以使用一个示例将给出有偏颇的结果。所以我决定使用两个示例:一个转换示例用于 XSLT,一个查询示例用于 XQuery。通过比较,将会发现为什么这些语言适用于不同的需要。

XML 文档

两个示例都在 清单 2 上运行,清单 2 是 RSS 中的文章列表。

清单 2. 文章列表
<?xml version="1.0"?>
<rss version="2.0">
 <channel>
  <title>Projects in the "Working XML" column</title>
  <description>A selection of ben's article on
     developerWorks.</description>
  <language>en</language>
  <link>http://www.ibm.com/developerWorks/xml</link>
  <item>
   <title>Safe coding practices</title>
   <pubDate>Fri, 6 May 2005 00:00:00 GMT</pubDate>
   <link>http://www.ibm.com/developerworks/xml/library/x-wxxm30.html</link>
   <description>Most common pitfalls and how to avoid them (4 parts).</description>
  </item>
  <item>
   <title>The Eclipse task list</title>
   <pubDate>Fri, 22 Oct 2004 00:00:00 GMT</pubDate>
   <link>http://www.ibm.com/developerworks/library/x-wxxm27/</link>
   <description>Various techniques on integrating XML and Eclipse (4 parts).</description>
  </item>
  <item>
   <title>XML, XMI and code generation</title>
   <pubDate>Wed, 31 Mar 2004 00:00:00 GMT</pubDate>
   <link>http://www.ibm.com/developerworks/xml/library/x-wxxm23/</link>
   <description>Using modeling for XML development (4 parts).</description>
  </item>
 </channel>
</rss>

XSLT 示例

清单 3 是 XSLT 样式表。它用 HTML 发布 RSS 文档。该样式表包含 清单 2 中每个元素的模板 (xsl:template),它依赖 XSLT 处理器选择最适合的模板。可以看到,样式表假设您将处理整个文档。XSLT 还将很好地处理混合元素。

清单 3. XSLT 样式表
<?xml version="1.0"?>
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="html"/>
   <xsl:template match="rss">
      <html>
         <head><title>
            <xsl:value-of select="channel/title"/>
         </title></head>
         <xsl:apply-templates/>
      </html>
   </xsl:template>
   <xsl:template match="channel/title">
      <h1><a href="{../link}"><xsl:apply-templates/></a></h1>
   </xsl:template>
   <xsl:template match="title">
      <h2><a href="{../link}"><xsl:apply-templates/></a></h2>
   </xsl:template>
   <xsl:template match="description">
      <p><xsl:apply-templates/></p>
   </xsl:template>
   <xsl:template match="pubDate | link | language"/>
</xsl:stylesheet>

注意声明方法:您指定如何处理元素,处理器(通过其内置的树遍历逻辑)决定何时应用模板。添加和移除模板很容易。代码不包含循环,因为处理器已经知道如何遍历文档。

XQuery 示例

清单 4 是 XQuery 示例。它运行两个查询:一个用于提取星期五发布的文章列表,一个用于列出讨论 XMI 的文章。

清单 4. XQuery
<result>
 {
  for $i in doc("rss.xml")/rss/channel/item
  where starts-with($i/pubDate/text(),"Fri")
  return
    <friday>
      { $i/title/text() }
    </friday>
 }
 {
  for $i in doc("rss.xml")/rss/channel/item
  where contains($i/title/text(),"XMI")
  return
    <xmi>
      { $i/title/text() }
    </xmi>
 }
</result>

比较 清单 4清单 3。在 XQuery 中,代码依赖于 XPath 直接指向感兴趣的元素,且循环必须显式编写。从文档中提取报告时,它十分理想。

决策时间

我开始使用 XSLT 2.0 和 XQuery 1.0 作为 XPath 2.0 的不同语支。每种语支适用于特定的应用程序。只有时间能说明这两种语支是否都将茁壮成长。就目前来看,我打算专注于 XPath 2.0,并根据要开发的应用程序使用最适合的语支。


相关主题

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文
  • XSLT 是什么类型的语言? 作者 Michael Kay:将 XSLT 放入上下文中:语言来自哪里,擅长什么,为何使用它(developerWorks,2005 年 4 月)。
  • Influences on the design of XQuery:阅读本文中有关 XQuery 语言的出现原因(应 XML 数据查询语言之需)及其基本原则,作者是 XQuery 的先驱 Don Chamberlin(developerWorks,2003 年 9 月)。
  • XML for Data: An early look at XQuery 作者 Kevin Williams:学习如何在 XQuery 中的重要位置使用 FLWR (flower) 子句(developerWorks,2002 年 2 月)。
  • XSLT 处理程序是如何工作的:在本文中与 Benoît Marchaland 一起研究了使 XSLT 惟一的树遍历逻辑(developerWorks,2004 年 3 月)。
  • developerWorks XML 专区:阅读文章和教程以扩展 XML 技能。
  • IBM XML 认证:了解如何成为 IBM 认证的 XML 及相关技术的开发人员。
  • Saxon:将 XSLT 和 XQuery 处理组合到 Saxon 中。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=110936
ArticleTitle=使用 XML: XSLT 2.0 和 XQuery 对比
publish-date=04302006