CSDN上无意中看到了这样一篇老帖 ,关于XSLT转换的。 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

XSLT原文:

<?xml   version="1.0"   encoding="GB2312"?>  
  <?xml-stylesheet   type="text/xsl"   href="sort.xsl"?>  
  <root>  
  <item   f1="
浙江 "   f2=" 绍兴 "   f3="aaa"/>  
  <item   f1="
江苏 "   f2=" 苏州 "   f3="bbb"/>  
  <item   f1="
浙江 "   f2=" 杭州 "   f3="ccc"/>  
  <item   f1="
山东 "   f2=" 济南 "   f3="ddd"/>  
  <item   f1="
山东 "   f2=" 青岛 "   f3="eee"/>  
  <item   f1="
江苏 "   f2=" 南京 "   f3="fff"/>  
  <item   f1="
山东 "   f2=" 青岛 "   f3="ggg"/>  
  <item   f1="
江苏 "   f2=" 南京 "   f3="hhh"/>  
  <item   f1="
山东 "   f2=" 济南 "   f3="iii"/>  
  </root>  

要转换的结果文件:
江苏 -   南京: fff hhh   苏州: bbb  
山东 -   济南: ddd iii   青岛: eee ggg  
浙江 -   杭州: ccc   绍兴: aaa  

意思是要把在同一个省同一个市的归纳在一起,并且省市都要按字典排序。

楼主想到了一点:轴是用在原文档中的。

其实,这个问题可以解决:

首先第一步:提取f1

代码:

< ?xml version='1.0'? >

< xsl:stylesheet version= "1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform" >

< xsl:template match= "/" >

   < xsl:apply-templates select= "root/item" >

      < xsl:sort select= "@f1" / >  

   < /xsl:apply-templates >

< /xsl:template >

< xsl:template match= "item" >

   < xsl:if test= "not(preceding-sibling::*[@f1=current()/@f1])" >

      < xsl:value-of select= "concat(@f1,'-')" / >

      < br/ >

   < /xsl:if >

< /xsl:template >

< /xsl:stylesheet >

OK, 可以得到下面的结果:

江苏 -
山东 -
浙江-
现在需要输出第二项内容:即f2,可是该如何实现呢?我们知道apply-templates,通常只应用于子孙节点的模板。第一步我们已经到了item了,下面就是属性了,应用属性的模板,该如何实现属性的唯一性输出呢?
其实打破常理来想,我们可以再次应用item的模板,但是如何应用呢?我们应该先利用for-each将当前节点移到item的顶层,那么就可以再次应用item的模板了,但是,另一个问题又出来了,再次应用这个模板,是不是会混乱了,我们这次的目的是输出f2啊,OK,还记得吗?<xsl:templates>有一个mode属性。代码也就顺理成章的出来了(当然还得保证所选定的item节点没变):
< ?xml version='1.0'? >

< xsl:stylesheet version= "1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform" >

< xsl:template match= "/" >

   < xsl:apply-templates select= "root/item" mode= "a" >

      < xsl:sort select= "@f1" / >  

   < /xsl:apply-templates >

< /xsl:template >

< xsl:template match= "item" mode= "a" >

   < xsl:if test= "not(preceding-sibling::*[@f1=current()/@f1])" >

      < xsl:value-of select= "concat(@f1,'-')" / >

      < xsl:variable name= "f1" select= "@f1" / >

      < xsl:for-each select= ".." >

         < xsl:apply-templates select= "item[@f1 = $f1]" mode= "b" >

            < xsl:sort select= "@f2" / >

         < /xsl:apply-templates >

      < /xsl:for-each >

      < br/ >

   < /xsl:if >

< /xsl:template >

< xsl:template match= "item" mode= "b" >

   < xsl:if test= "not(preceding-sibling::*[@f2=current()/@f2])" >

      < xsl:value-of select= "concat(' ',@f2,':')" / >

   < /xsl:if >

< /xsl:template >

< /xsl:stylesheet >