以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XSL/XSLT/XSL-FO/CSS 』  (http://bbs.xml.org.cn/list.asp?boardid=8)
----  XSLT2.0新特性体验之一——分组的简化[原创]  (http://bbs.xml.org.cn/dispbbs.asp?boardid=8&rootid=&id=16265)


--  作者:doubleG
--  发布时间:3/30/2005 5:13:00 PM

--  XSLT2.0新特性体验之一——分组的简化[原创]
XSLT2.0已经出来时间不短了,由于时间关系一直没有好好去看,最近抽点时间和大家一起讨论一下喽:)
XSLT2.0相比1.0增加了五个比较激动人心的功能
今天就来看看第一个:支持分组了。在1.0中我们要对XML分组虽然可以使用很多方式,但是就算最出名的Muenchian虽然灵巧但是其复杂耗内存的方法并不受人们的推崇,在2.0中有了直接的支持,使得XML中的分组不再令人生畏,下面我们就来比较一下1.0和2.0中的分组:
数据文件:node.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml:stylesheet type="text/xsl" href="1.xsl"?>
<root>
 <node a="a1" b="b1"/>
 <node a="a2" b="b1"/>
 <node a="a2" b="b2"/>
 <node a="a3" b="b2"/>
</root>
目标结果输出:
The a: a1  a2  a3  
The b: b1  b2  


在1.0中没有直接的分组功能必须自己想办法来进行处理,我就拿Muenchian方法来做例子了(毕竟是最灵巧的方法,呵呵)
1.xsl(1.0版):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
 <xsl:key name="nodeA" match="node" use="@a"/>
 <xsl:key name="nodeB" match="node" use="@b"/>
 <xsl:template match="root">
  The a:
  <xsl:for-each select="./node[generate-id(.)=generate-id(key('nodeA',@a))]">
   <xsl:value-of select="@a"/> 
  </xsl:for-each>
  <br/>
  The b:
  <xsl:for-each select="./node[generate-id(.)=generate-id(key('nodeB',@b))]">
   <xsl:value-of select="@b"/> 

  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

设定两个key值,一个名字为nodeA,一个为nodeB。他们分别都是对于node这个节点进行分组设定的,只是分组所使用的内容不同,nodeA使用的是node的a属性,nodeB使用的是b属性。
generate-id(node-set):
The generate-id function returns a string that uniquely identifies the node in the argument node-set that is first in document order.
该函数会返回节点在整个文档中的唯一标识。
node-set key(string, object)
第一个参数是key名字,就是前面定义的<xsl:key的名字,object表示那个内容和key中的内容进行匹配,key('nodeA',@a)就是返回了第一个和当前节点的匹配内容相同的文档中的节点。
在上述的xsl中,我们添加进这样一段
<xsl:for-each select="./node">
 <xsl:value-of select="generate-id(.)"/> 
 <xsl:value-of select="generate-id(key('nodeA',@a))"/>
 <br/>
</xsl:for-each>
可以看到输出值是
IDAWHIYF  IDAWHIYF
IDAZHIYF  IDAZHIYF
IDA2HIYF  IDAZHIYF
IDATGIYF  IDATGIYF
可以看到空格前的四个数据是完全不相同的,也就是每一个节点的唯一标示,使随机生成并没有固定值,但空格后的数据第二个和第三个是相同的。我们可以看一下xml数据的第二个和第三个节点:
<node a="a2" b="b1"/>
<node a="a2" b="b2"/>
他们的a属性是相同,所以说明key('nodeA',@a)在处理到第三个节点<node a="a2" b="b2"/>时返回的是符合key的第一个节点,也就是<node a="a2" b="b1"/>。
通过这种"./node[generate-id(.)=generate-id(key('nodeA',@a))]"方式就剔除重复的内容,达到了分组效果,解析结果就是:
The a: a1  a2  a3  
The b: b1  b2  

是不是很复杂啊,xslt2.0解决了这个难题,我们看一下2.0的程序:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes">
 <xsl:output method="html"/>
 <xsl:template match="root">
  The a:
  <xsl:for-each-group select="node" group-by="@a">
   <xsl:value-of select="@a"/>> 
  </xsl:for-each-group>
  <br/>
  The b:
  <xsl:for-each-group select="node" group-by="@b">
   <xsl:value-of select="@b"/>> 
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>


只是使用了一个语句:for-each-group 通过group-by属性就将数据进行了分组,和SQL中的group-by很像对吗?它本身还有一些属性设置,往后再一一道来。

这篇文章的目的告诉大家,虽然xslt2.0的内容多了,但是对于一些操作确是简化了不少:)



--  作者:doubleG
--  发布时间:3/31/2005 11:10:00 AM

--  
55555~~~~~ 我写的东西总是没人看,失败啊。哪里写的不好也要提出来啊,不然都没有兴趣写了。我知道我的表达差,但是大家也要给意见啊。
--  作者:殷千炀
--  发布时间:3/31/2005 4:36:00 PM

--  
很好很好~加油加油!!
--  作者:sam
--  发布时间:4/1/2005 1:37:00 PM

--  
让admin给你 精 一下
--  作者:jx27
--  发布时间:6/21/2005 8:45:00 AM

--  
不错!我还想知道一下XSL2的其他情况!!
--  作者:chenshijun
--  发布时间:6/24/2005 6:45:00 PM

--  
我还要看XSLT2.0其他内容
望提供
Thank you
!
--  作者:smxwjd
--  发布时间:7/1/2005 9:14:00 PM

--  
XLST 多文件输出,不知道楼主有没有此类资料或代码?

Thank You^_^


--  作者:Qr
--  发布时间:7/2/2005 2:59:00 PM

--  
以下是引用smxwjd在2005-7-1 21:14:57的发言:
XLST 多文件输出,不知道楼主有没有此类资料或代码?

Thank You^_^



XSLT2.0增加了<xsl:result-document>,可实现多文档输出,用它GOOGLE一下,答案就在其中。
--  作者:smxwjd
--  发布时间:7/4/2005 10:29:00 AM

--  
请问楼主,知道哪几个解析器支持XSLT2.0吗?

谢谢,不知道IE6.0中的MSXML3.0支持XSLT2.0吗?


--  作者:admin
--  发布时间:7/5/2005 12:16:00 AM

--  
XMLSpy 2005是支持XSLT 2.0 的

以下是引用smxwjd在2005-7-4 10:29:41的发言:
请问楼主,知道哪几个解析器支持XSLT2.0吗?

谢谢,不知道IE6.0中的MSXML3.0支持XSLT2.0吗?



--  作者:wzzwj
--  发布时间:7/9/2005 6:06:00 PM

--  
楼主的文章非常好,不过其中有几个小问题。
一个是关于key函数的解释:
node-set key(string, object)
第一个参数是key名字,就是前面定义的<xsl:key的名字,object表示那个内容和key中的内容进行匹配,key('nodeA',@a)就是返回了第一个和当前节点的匹配内容相同的文档中的节点。

实际上key会将所有与第二个参数相等的节点都返回。这在XSLT规范中也有说明。至于楼主通过实验,得出下面的结论也是错的:
所以说明key('nodeA',@a)在处理到第三个节点<node a="a2" b="b2"/>时返回的是符合key的第一个节点,也就是<node a="a2" b="b1"/>。
这是因为generate-id函数的作用,在XSLT规范中关于这个函数有以下说明:
The generate-id function returns a string that uniquely identifies the node in the argument node-set that is first in document order.
我的理解是返回节点集中的第一个节点的唯一标识符。也就是说,在处理<node a="a2"...>节点时,key函数返回了包含两个节点的列表:<node a="a2" b="b1"/>和<node a="a2" b="b2"/>,而generate-id函数取节点集中的第一个节点产生唯一标识符,然后进行比较。
呵呵,因为有别的事,所以写的比较匆忙。不知是否表述清楚。
为了证明我说的,给楼主提供一个模板规则,如下:
<xsl:key name="nodeA" match="node" use="@a"/>
 <xsl:key name="nodeB" match="node" use="@b"/>
 <xsl:template match="node">
  The a:
      <xsl:copy-of select="key('nodeA',@a)"/>
 </xsl:template>
希望楼主能多写的这样的文章,希望能多交流。如果我的理解不对,也请达人指出。


--  作者:lazyy
--  发布时间:7/9/2005 9:07:00 PM

--  
谢谢了,希望与更多的后继内容,
--  作者:一叶千鸟
--  发布时间:8/7/2005 12:04:00 AM

--  
原来如此 group-by 是2.0提供的

上次在1.0下调试怎么都不行


--  作者:kevinxu
--  发布时间:10/25/2005 8:03:00 AM

--  
很好很好。
--  作者:zkj8421
--  发布时间:11/27/2005 8:11:00 PM

--  
good
--  作者:cthily
--  发布时间:3/23/2006 3:12:00 PM

--  
支持,经验是就重要的。呵呵。。。。。
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.125ms