分享
 
 
 

XSLT 2.0 的新特性

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

body{font-size:small;}

pre,code{font-family: "courier new"}

pre {background-color:#e1e1e1}

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:result的select属性中完成的。这个样式表调用了用户自定义的一个递归函数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。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有