使用Xsl 來替 Xml文件排序

使用Xsl 來替 Xml文件排序

參考文獻:Sorting an XML document in C# using XSL

 

Paul大師很棒的做出一個很簡單的sample code

讓我們只要用


<xsl:sort>
<xsl:copy-of>

可以馬上將Xml Document 排序.

 

以下為延伸的應用, 至於C#程式碼我就不PO文, 請參考Paul大師的samle

 

一、屬性篇

因為本人習慣用attribute, 所以改了一下

 

二、文字篇

當然也可以針對文字排序

 

三、正序篇

範例是用倒序, 我們可以改成正序

 

四、多層次篇

以上都只是xsl的基本功, 

但如同往常, 只要碰到要跑loop或是要遞迴的, 一定會踢到鐵板

 

我的資料如下: 是多層的, 而且值是放在attribute


  <Link ID="Q1" path="我的最愛">
    <Link ID="Q11" path="建築">
      <Link ID="Q111" path="設計師">
        <Link ID="Q1111" path="隈研吾">
          <Link ID="Q11111" path="三多利美術館" />
          <Link ID="Q11112" path="森舞台" />
        </Link>
        <Link ID="Q1112" path="謝瑞夫" />
      </Link>
      <Link ID="Q112" path="營造商">        
      </Link>
    </Link>
  </Link>
  <Link ID="Q2" path="公司系統" />
</Links>

而程式希望各項目能夠依 ID 在自己的層次中倒序.

首先 <xsl:copy-of> 會把所有的子項目都倒出來, 所以不適合

改用 <xsl:copy> 原本預期它將整個項目包含屬性一次複製, 結果它很懶, 所以只好加一句for-each讓它跑一次loop


      <xsl:for-each select="./@*">
        <xsl:copy />      
      </xsl:for-each>      

另外要讓它向下探勘項目也花了一點功夫


      <xsl:for-each select=".">
        <xsl:apply-templates select="Link" >
          <xsl:sort select="@ID" data-type="text" order="descending"/>
        </xsl:apply-templates>
      </xsl:for-each>

完整Xsl 如下:



<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  
  <xsl:template match="Links">
    <xsl:copy>    
      <xsl:for-each select=".">
        <xsl:apply-templates select="Link" >
          <xsl:sort select="@ID" data-type="text" order="descending"/>                  
        </xsl:apply-templates>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="Link" >
    <xsl:copy>
      <!-- 複製屬性 -->
      <xsl:for-each select="./@*">
        <xsl:copy />      
      </xsl:for-each>      
      <!-- 向下探勘 -->
      <xsl:for-each select=".">
        <xsl:apply-templates select="Link" >
          <xsl:sort select="@ID" data-type="text" order="descending"/>
        </xsl:apply-templates>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>                
  
</xsl:stylesheet>

 

輸出結果如下:


<Links>
	<Link ID="Q2" path="公司系統"/>
	<Link ID="Q1" path="我的最愛">
		<Link ID="Q11" path="建築">
			<Link ID="Q112" path="營造商"/>
			<Link ID="Q111" path="設計師">
				<Link ID="Q1112" path="謝瑞夫"/>
				<Link ID="Q1111" path="隈研吾">
					<Link ID="Q11112" path="森舞台"/>
					<Link ID="Q11111" path="三多利美術館"/>
				</Link>
			</Link>
		</Link>
	</Link>
</Links>

本來是想用LINQ2XML 做的, 但剛好那個Site只支援 .NET 2.0 (有機會再分享囉)