正如原来问题的楼主所说:preceding-sibling是指在上下文节点在原XML文档中的前驱节点集合。所以在mode b中的代码:
< xsl:if test= "not(preceding-sibling::*[@f2=current()/@f2])" > <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

是判断在此之前没有出现过相同的f2,preceding-sibling没错,但是这里有一个前提条件:同一个f1,在原文件中如果当前节点存在一个相同的f2,但不是同一个f1,那么当前节点的f2将无法输出了。
如果说f2(代表的是城市)很难有同名的,但是mode c呢,
< xsl:if test= "not(preceding-sibling::*[@f3=current()/@f3])" >

f3同名的多了吧,更何况,有没有同名的城市还很难说呢。
总之为了程序的严密性,我们必须将其改成:
< ?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::*[@f1=current()/@f1][@f2=current()/@f2])" >

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

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

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

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

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

         < /xsl:apply-templates >

      < /xsl:for-each >

   < /xsl:if >

< /xsl:template >

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

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

      < xsl:if test= "position()!=1" >

         < xsl:value-of select= "','" / >

      < /xsl:if >

      < xsl:value-of select= "@f3" / >

   < /xsl:if >

< /xsl:template >

< /xsl:stylesheet >

其实,最重要的一点就是清楚程序每个步骤执行的状态,并有一个清晰的模型,到底是在原 XML 文档,还是节点集合。