`
persistC
  • 浏览: 71433 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

XSLT 2.0 的新特性

    博客分类:
  • XSLT
阅读更多

XSLT 2.0 的新特性

关键字: XSLT, XML
原作:Evan Lenz 2002.4.10, onestab 译自 www.xml.com

本文将看看最新的工作草案中所列出的XSLT2.0的一些新特性,当然,假定你已经熟悉XSLT/XPath1.0的基本知识。

XSLT 2.0 和 XPath 2.0

XSLT 2.0 与 XPath 2.0 携手并肩。之所以将它们分开描述,是因为 XPath 2.0 也可用于XSLT之外的环境,比如XQuery 1.0。但是对于XSLT用户来说,它们是互相关联的。你不能在XSLT 1.0 中使用 XPath 2.0,或者在 XSLT 2.0 中使用 XPath 1.0。(至少到目前为止,W3C还没有这种组合的提议。)

你也许会问:XSLT 1.1 发生了什么?XSLT 1.1 已经取消了。官方的说法是在2001年8月,实际上在几个月前,XSLT工作组中止了XSLT 1.1,集中力量开发XSLT和XPath 2.0,将XSLT 1.1 的前期要求转到XSLT 2.0。

欢迎到来

许多的XSLT用户在很大程度上参与了新版XSLT的制订过程。就像许多语言的第一版一样,不经过实践的检验,这个语言的哪些扩展被证明是最重要的往往不很清楚。自从1999年11月16日XSLT 1.0 成了推荐标准以后,显然在某些方面缺少的功能应当在下一个版本中包括进来,本文我们将从下面四个方面看看XSLT 2.0:

  • 从结果树片断(result tree fragments)到节点集(node-sets)的转化
  • 有多个输出的文档
  • 对分组的内在支持
  • 用户定义函数(以XSLT实现)

RTF的末日

在XSLT 1.0 中结果树片断(Result Tree Fragment,RTF)类型很像节点集,实际上却是个二等公民。当你使用xsl:variable构建一个临时树的时候,得到的就是RTF。问题是你不能使用XPath表达式访问这个树的内容,除非你使用一个供应商提供的扩展函数,通常是node-set()之类,来把这个RTF转化成一类节点集(含有一个根节点)。这种RTF数据类型的存在本来是为了减少实现时的限制,但由于几乎所有的XSLT处理器都提供诸如node-set()之类的扩展函数,这种考虑显得有些不切实际。不管怎样,突破这种限制的呼声总会越来越明显,因为把复杂的变换分解成一系列简单的变换非常重要。

不知道你有没有猜出来,XSLT 2.0 为RTF打开了这个门。现在当你使用xsl:variable创建一个临时树,这个变量的值就是个真正的节点集。事实上,用XPath 2.0 的术语来讲,它是个真正的节点序列(true node sequence),包含一个 document node (这是一个XPath 2.0 的名称,也就是XPath 1.0 的"root node")。在这个序列上你可以使用XPath表达式深入到这棵树,对它应用模板(template)等等,就像使用其它源文件一样。有了XLST 2.0 就不再需要node-set()之类的扩展函数。

允许多个输出文档

许多XSLT 1.0 处理器所提供的另一个扩展就是多个输出文档,这种扩展被证明非常有用,对具有多个页面的网站的静态生成尤其如此。问题在于这个扩展功能不是标准的。每个处理器完成这种扩展的元素都不一样,例如 saxon:output, xt:document等等。

XSLT 2.0 使用 xsl:result-document元素提供了多个输出文档的一个标准方法。下面的样式表例子构建了多个输出文档,一个“主要结果文件”和几个“次级结果文件”。主要结果文件以XHTML存储,次级结果文件以纯文本方式存储。

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output method="xhtml"/>
  <xsl:output method="text" name="textFormat"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>Links to text documents</title>
      </head>
      <body>
        <p>Here is a list of links to text files:</p>
        <ul>
          <xsl:apply-templates select="//textBlob"/>
        </ul>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="textBlob">
    <xsl:variable name="uri" select="concat('text', position(), '.txt')"/>
    <li>
      <a href="{$uri}">
        <xsl:value-of select="$uri"/>
      </a>
    </li>
    <xsl:result-document href="{$uri}" format="textFormat">
      <xsl:value-of select="."/>
    </xsl:result-document>
  </xsl:template>
</xsl:stylesheet>

xsl:document href 属性用来为相应的输出文件指定一个URI。对于许多处理器来说,这意味着以该文件名存储文件。而format属性用来引用一个已命名的指定输出。在这里,它指向以textFormat命名的xsl:output元素。

上例中的XHTML输出方式也是在XSLT 2.0中新引入的,这里勿须赘言。

简化的分组

XSLT 1.0 没有对分组的内在支持。特定的分组问题无疑可使用各种技巧解决,例如Muenchian方法,但是这种解决方法相当复杂难懂。对XSLT 2.0 的要求之一就是必须要简化分组,就像我们在下例中所看到的,这种方法能满足要求。

出现在 Requirements document 和XSLT 2.0 工作草案的这个例子是关于把下面简单XML文档中的城市列表,

<cities>
  <city name="milan"  country="italy"   pop="5"/>
  <city name="paris"  country="france"  pop="7"/>
  <city name="munich" country="germany" pop="4"/>
  <city name="lyon"   country="france"  pop="2"/>
  <city name="venice" country="italy"   pop="1"/>
</cities>

转换为如下所示的以国家进行分组的HTML表格:

<table>
   <tr>
      <th>Country</th>
      <th>City List</th>
      <th>Population</th>
   </tr>
   <tr>
      <td>italy</td>
      <td>milan, venice</td>
      <td>6</td>
   </tr>
   <tr>
      <td>france</td>
      <td>paris, lyon</td>
      <td>9</td>
   </tr>
   <tr>
      <td>germany</td>
      <td>munich</td>
      <td>4</td>
   </tr>
</table>

这种转换的难点在于生成最后三行(如粗体所示)。下面是XSLT1.0的一种解决方案:

  <xsl:for-each select="cities/city[not(@country =
                           preceding::*/@country)]">
    <tr>
      <td><xsl:value-of select="@country"/></td>
      <td>
        <xsl:for-each select="../city[@country = current()/@country]">
          <xsl:value-of select="@name"/>
          <xsl:if test="position() != last()">, </xsl:if>
        </xsl:for-each>
      </td>
      <td><xsl:value-of select="sum(../city[@country =
                 current()/@country]/@pop)"/></td>
    </tr>
  </xsl:for-each>

在上例中,对每个特定的国家,我们首先要用下面的XPath表达式找出它的第一个城市:

cities/city[not(@country = preceding::*/@country)]

然后,对每个分组,为了获得每个国家的城市名字列表以及该国的总人口,我们需要再回头引用该组的所有其他成员,这两种情况我们不得不作一些额外的工作,因为只能用下面的表达式才能引用到当前的分组:

../city[@country = current()/@country]

显然这不是个理想的局面,因为这种额外的代码往往是错误之源。 使用 xsl:for-each-group, XSLT 2.0 为你的大多数分组问题提供了答案。下面就是XSLT2.0对这个问题的解决办法(粗体表示新特性):

  <xsl:for-each-group select="cities/city" group-by="@country">
    <tr>
      <td><xsl:value-of select="@country"/></td>
      <td>
        <xsl:value-of select="current-group()/@name" separator=", "/>
      </td>
      <td><xsl:value-of select="sum(current-group()/@pop)"/></td>
    </tr>
  </xsl:for-each-group>

在上例中,xsl:for-each-group 作为XPath的取值上下文的一部分,对"current group"进行初始化,当前的分组是一个简单序列。一旦我们使用group-by属性设置好分组,以后就可以使用current-group()函数引用当前的分组。这就完全消除了XSLT1.0方案中的额外开销。

注意xsl:value-of中的separator属性。这个属性的存在是为了告诉处理器不只是要输出这个序列中的第一个元素的string值(XSLT1.0是如此作的),而是要按顺序输出该序列中所有元素的值。separator属性的取值为一个可选的字符串,用作输出中每个字符串的分隔符。为了与XSLT1.0兼容,如果没有指定separator属性,只输出该序列中的一个成员的值。

 

最后,根据xsl:for-each-group的三个属性的取值,可以解决不同的分组问题:group-by(如上面所示),goup-adjacent(用于根据文当中的节点顺序的相邻关系进行分组,例如将inline的<para>元素转化为块级(block)的<para>元素),以及group-start-with(根据序列中元素的模式(patterns)分组)。这些方法的例子可以在最新的XSLT2.0工作草案的"13.3 Examples of Grouping"中找到。

用户定义函数

XSLT2.0引入了一个新特性,就是允许定义他们自己的函数,并可以在Xpath表达式中使用。这是个非常强大的功能,无疑是非常有用的。样式函数(Stylesheet functions)是用xsl:function元素定义的。这个元素必须指定一个name属性。它包含0个或多个xsl:param元素,然后是0个或多个xsl:variable元素,后面是唯一的xsl:result元素。这种严格的内容模型看起来是个限制,但是你会发现XSLT2.0的真正强大之处就在于可定义xsl:result元素的select属性。你可能会想到,XPath2.0具备有条件表达式(if...then)和迭代(iterative)(列举?)表达式(for...return)。

就像下面例子(直接取于最新的工作草案)所示,许多工作是在xsl:resultselect属性中完成的。这个样式表调用了用户自定义的一个递归函数str:reverse()来输出字符串"MAN BITES DOG"。

<xsl:transform 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:str="http://user.com/namespace"
  version="2.0"
  exclude-result-prefixes="str">
<xsl:function name="str:reverse">
  <xsl:param name="sentence"/>
  <xsl:result 
     select="if (contains($sentence, ' '))
             then concat(str:reverse(substring-after($sentence, ' ')),
                         ' ',
                         substring-before($sentence, ' '))
             else $sentence"/>             
</xsl:function>
<xsl:template match="/">
<output>
  <xsl:value-of select="str:reverse('DOG BITES MAN')"/>
</output>
</xsl:template>
</xsl:transform>

其他有用的东西动手试试

XSLT2.0还有其他有用的新特性,我们在这里难以祥述。包括一种机制,可定义XPath表达式的缺省名称空间(namespace),可在模式匹配判定(match pattern predicates)中使用变量,为排序说明命名(named sort specifications),以非解析文本(unparsed text)的方式读入外部文件等等。

此外,XSLT2.0说明书的一大部分仍在制订中,特别是有关构建和复制W3C XML Schema类型的内容。关于这点,最新的工作草案中说,“这项工作正在进行,有关构建元素和属性的类型信息关联,将可能会出现在XSLT2草案的未来版本中。(This is work in progress. Facilities for associating type information with constructed elements and attributes are likely to appear in future drafts of XSLT 2)”。

如果你迫不及待地想试试这些新东西,Michael Key已经发布了Saxon 7.0,包含一个“实现XSLT2.0和XPath2.0的尝试”。它实现了XSLT2.0和XPath2.0的一些新特性,特别值得关注的是这些特性看起来非常稳定。我对本文中的每个例子都作了测试,正如所期待的那样,Saxon 7.0 能够全部运行这些例子。

XSLT2.0很大程度上仍然处于起草阶段,所以要预先指出,从目前阶段到成为推荐标准中间,有些东西可能会发生变化。目前,鼓励大家浏览说明文件并将他们的观点发送到 xsl-editors@w3.org。

分享到:
评论

相关推荐

    2.ASP.NET.2.0.高级编程(第4版) [1/7]

    内容简介回到顶部↑本书全面介绍了ASP.NET各种编程技能和2.0版中的巨大变化,并详细阐述了2.0版中的每个新特性。书中提供了大量的实例,可帮助读者快速掌握如何在.NET平台下开发功能强大的ASP.NET应用程序。本书适合...

    Spring 2.0 开发参考手册

    2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@...

    ASP.NET2.0高级编程(第4版)1/6

    本书全面介绍了ASP.NET各种编程技能和2.0版中的巨大变化,并详细阐述了2.0版中的每个新特性。书中提供了大量的实例,可帮助读者快速掌握如何在.NET平台下开发功能强大的ASP.NET应用程序。本书适合有一些基础的ASP...

    xmlspy.2013-patch

    XSL / XSLT1.0/2.0编辑器,XSLT调试器和分析器XSLT 图形的XML编辑和基于文本的XML编辑视图 模式感知的XQuery XQuery编辑器,调试器和XQuery的分析器 革命性的智能修复XML验证自动纠错 XPath的自动完成和XPath分析器...

    altova-xmlspy-enterprise-2010-v12-3

    XSL / XSLT1.0/2.0编辑器,XSLT调试器和分析器XSLT 图形的XML编辑和基于文本的XML编辑视图 模式感知的XQuery XQuery编辑器,调试器和XQuery的分析器 革命性的智能修复XML验证自动纠错 XPath的自动完成和XPath分析器...

    asp.net知识库

    我眼中的C#2.0新功能特性 泛型技巧系列:避免基类及接口约束 New Article 不该用Generics实现Abstract Factory的理由 C#2.0-泛型 C#2.0-extern C#2.0-可空类型 C#2.0-分部类 C#2.0-迭代器 C#2.0 的新增功能学习 泛型...

    北京中科信软 Visual Basic.NET培训

    C#中的新特性 程序集 .NET应用程序部署和版本控制 委托和事件 线程 反射 对象序列化 数据流和文件 Internet访问与网络编程 EventLog MSMQ Remoting 与COM的交互 Windows Service 三 ADO.NET 数据库...

    \JavaScript权威指南(第五版)

    本书第五版已经经过全面地修订和扩展,涵盖了构建当今Web2.0应用程序所需的JavaScript技术。本书不仅是一本实例驱动的程序员指南,同时也是一本可以摆在桌边随时查阅的参考手册,它以全新的章节阐述了有效使用...

    xml入门经典-part3(中文版)

    6.5 SAX 2.0 6.5.1 可配置的接口 6.5.2 核心的特性和属性 6.6 小结 第7章 命名空间和模式 7.1 混合词汇表 7.1.1 分解问题 7.1.2 重用 7.1.3 二义性与名称冲突 7.2 命名空间 7.3 定义和声明命名空间 7.3.1...

    X3BLOG 单用户版 1.0 build80707 (access)

    X3BLOG 是基于XML+XSLT+AJAX技术构建的开源多用户博客门户系统,服务器端采用当前最流行的动态网页开发语言ASP.NET(C#) 2.0编写,支持多种数据库,包括SQLSERVER2000\SQLSERVER2005\ORACLE等,默认使用SQLSERVER2000...

    X3BLOG 单用户 v1.0 build 080802 源码版

    X3BLOG 是基于XML+XSLT+AJAX技术构建的开源多用户博客门户系统,服务器端采用当前最流行的动态网页开发语言ASP.NET(C#) 2.0编写,支持多种数据库,包括SQLSERVER2000\SQLSERVER2005\ORACLE等,默认使用SQLSERVER2000...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

    包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、 XSLT相关类。当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。 (13) spring-mock.jar  这个jar文件包含...

    XML高级编程pdf

    6.5 SAX 2.0 6.5.1 可配置的接口 6.5.2 核心的特性和属性 6.6 小结 第7章 命名空间和模式 7.1 混合词汇表 7.1.1 分解问题 7.1.2 重用 7.1.3 二义性与名称冲突 7.2 命名空间 7.3 定义和声明命名空间 7.3.1...

    XML高级编程 (Extensible Markup Language)

    6.5 SAX 2.0 6.5.1 可配置的接口 6.5.2 核心的特性和属性 6.6 小结 第7章 命名空间和模式 7.1 混合词汇表 7.1.1 分解问题 7.1.2 重用 7.1.3 二义性与名称冲突 7.2 命名空间 7.3 定义和声明命名空间 7.3.1...

    XML 高级编程(高清版)

    6.5 SAX 2.0 6.5.1 可配置的接口 6.5.2 核心的特性和属性 6.6 小结 第7章 命名空间和模式 7.1 混合词汇表 7.1.1 分解问题 7.1.2 重用 7.1.3 二义性与名称冲突 7.2 命名空间 7.3 定义和声明命名空间 7.3.1...

    XML高级编程

    6.5 SAX 2.0 187 6.5.1 可配置的接口 187 6.5.2 核心的特性和属性 188 6.6 小结 189 第7章 命名空间和模式 191 7.1 混合词汇表 192 7.1.1 分解问题 193 7.1.2 重用 193 7.1.3 多义性名称冲突 193 7.2 命名空间 195 ...

    spring chm文档

    2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@...

    J2EE应用开发详解

    172 10.5 小结 177 第11章 EJB 179 11.1 EJB简介 179 11.1.1 EJB的特点 179 11.1.2 EJB类型与组成 180 11.1.3 EJB 3.0的新特性 181 11.2 元数据注释和部署描述符 181 11.2.1 元数据注释 181 11.2.2 部署描述符 182 ...

Global site tag (gtag.js) - Google Analytics