2013-12-20 71 views
1

晚上好大家好,XSLT的倍數水平排序

我創建了一個小程序,以便能夠全部包含在一個目錄(及其所有子目錄也)音頻文件進行排序。我收集所有的信息在C#中以產生下面的XML文件(以下XML是一個精簡版,我刪除了這裏並不需要的所有屬性):

<Directory Name="Compilations" > 
    <Directory Name="Compil - 2010" > 
    <File MediaTitle="4 Min" MediaAlbum="AA" MediaYear="2010" MediaArtists="Madonna" /> 
    <File MediaTitle="Beggin" MediaAlbum="AA" MediaYear="2010" MediaArtists="Madcon" /> 
    </Directory> 
</Directory> 

,我想下面的結果:

<MediaYear Year="2010"> 
    <MediaArtists Artist="Madonna"> 
    <MediaAlbum Album="AA"> 
     <File MediaTitle="4 Min" MediaAlbum="AA" MediaYear="2010" MediaArtists="Madonna" /> 
    </MediaAlbum> 
    </MediaArtists> 
    <MediaArtists Artist="Madcon"> 
    <MediaAlbum Album="AA"> 
     <File MediaTitle="Beggin" MediaAlbum="AA" MediaYear="2010" MediaArtists="Madcon" /> 
    </MediaAlbum> 
    </MediaArtists> 
</MediaYear> 

所有 「文件」 事件應該被排序如下方式:

  • 藝術家
  • 專輯

的XSLT代碼,我使用的是如下:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:strip-space elements="*" /> 

    <xsl:key match="File[@MediaYear != 0]" name="MediaYears" use="@MediaYear"/> 

    <xsl:template match="/"> 

    <xsl:for-each select="//File[generate-id(.)= generate-id(key('MediaYears', @MediaYear)[1])]"> 

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

     <MediaYear> 

     <xsl:attribute name="Year"> 

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

     </xsl:attribute> 

     <xsl:for-each select="key('MediaYears', @MediaYear)"> 

      <xsl:copy> 

      <xsl:copy-of select="node() | @* | node()"/> 

      </xsl:copy> 

     </xsl:for-each> 

     </MediaYear> 

    </xsl:for-each> 

    </xsl:template> 

</xsl:stylesheet> 

但這個代碼僅適用於分類的第一級,所以我想通過添加,添加第二個級別這一段代碼:

<xsl:key match="//File[@MediaArtists != '']" name="AlbumArtists" use="@MediaArtists"/> 

<xsl:template match="/"> 

    <xsl:variable name="VPass1"> 

    <xsl:call-template name="YearProcess"/> 

    </xsl:variable> 

    <xsl:apply-templates mode="Artist_Display" select="ext:node-set($VPass1)"/> 

</xsl:template> 

和我改變了現有的xsl:模板爲以下:

<xsl:template match="/" name="YearProcess" mode="Year_Display"> 

,我增加了以下模板:

<xsl:template match="/" mode="Artist_Display"> 

    <xsl:for-each select="//File[generate-id(.)= generate-id(key('AlbumArtists', @MediaArtists)[1])]"> 

    <xsl:sort select="ancestor::MediaYear[1]/@Year"/> 

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

    <MediaArtists> 

     <xsl:attribute name="AlbumArtists"> 

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

     </xsl:attribute> 

     <xsl:attribute name="AlbumYear"> 

     <xsl:value-of select="ancestor::MediaYear[1]/@Year"/> 

     </xsl:attribute> 

     <xsl:for-each select="key('AlbumArtists', @MediaArtists)"> 

     <xsl:copy> 

      <!--<xsl:copy-of select="ancestor::MediaYear[1]"/>--> 

      <xsl:copy-of select="node() | @* | node()"/> 

     </xsl:copy> 

     </xsl:for-each> 

    </MediaArtists> 

    </xsl:for-each> 

</xsl:template> 

而且我沒有得到預期的結果,我是很新,XSLT如果答案已經存在原諒我,我搜索但我有點迷路,我不知道要搜索什麼。

我敢肯定這是不是很清楚,如果需要,可這裏的代碼:

https://github.com/jaguar0076/FileManager/blob/master/FileManager/Stylesheet.xslt

我不知道去哪裏,也許是muenchian方法是不是最好的方法實現我想要的。

感謝您的幫助,您可以提供,

羅德里格

編輯:標題改爲

回答

2

這是一個基於創建三個密鑰的解決方案。

<xsl:output method="xml" indent="yes"/> 

    <xsl:strip-space elements="*" /> 

    <xsl:key match="File[@MediaYear != 0]" name="MediaYears" use="@MediaYear"/> 

    <!-- the following key has been designed on the assumption that MediaYear never contains a space--> 
    <xsl:key match="File[@MediaArtists != '']" name="MediaArtists" use="concat(@MediaYear, ' ', @MediaArtists)"/> 

    <!-- the following key has been designed on the assumption that MediaYear never contains a space 
    AND MediaArtists never contains a %--> 
    <xsl:key match="File[@MediaAlbum != '']" name="MediaAlbum" use="concat(@MediaYear, ' ', @MediaArtists, '%', @MediaAlbum)"/> 

    <xsl:template match="/"> 

    <xsl:for-each select="//File[generate-id(.)= generate-id(key('MediaYears', @MediaYear)[1])]"> 

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

     <MediaYear Year="{@MediaYear}"> 

     <xsl:variable name="MediaYear" select="@MediaYear"/> 
     <xsl:for-each select="//File[@MediaYear=$MediaYear and generate-id(.)= generate-id(key('MediaArtists', concat(@MediaYear, ' ', @MediaArtists))[1])]"> 

      <xsl:sort select="@MediaArtists"/> 
      <MediaArtists Artist="{@MediaArtists}"> 
      <xsl:variable name="MediaArtists" select="@MediaArtists"/> 

      <xsl:for-each select="//File[@MediaYear=$MediaYear and @MediaArtists=$MediaArtists and generate-id(.)= generate-id(key('MediaAlbum', concat(@MediaYear, ' ', @MediaArtists, '%', @MediaAlbum))[1])]"> 
       <xsl:sort select="@MediaAlbum"/> 

       <MediaAlbum Album="{@MediaAlbum}"> 
       <xsl:variable name="MediaAlbum" select="@MediaAlbum"/> 
       <xsl:for-each select="//File[@MediaYear=$MediaYear and @MediaArtists=$MediaArtists and @MediaAlbum=$MediaAlbum]"> 
        <xsl:copy> 

        <xsl:copy-of select="node() | @* | node()"/> 

        </xsl:copy> 
       </xsl:for-each> 
       </MediaAlbum> 
      </xsl:for-each> 
      </MediaArtists> 
     </xsl:for-each> 

     </MediaYear> 

    </xsl:for-each> 


    </xsl:template> 

</xsl:stylesheet> 
1

如果您的處理器支持EXSLT(因爲它從你的代碼似乎),你可以使用set: distinct()函數而不是Muenchian分組。例如,像:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:set="http://exslt.org/sets" 
extension-element-prefixes="set"> 

<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

<xsl:key name="fileByYear" match="File" use="@MediaYear" /> 
<xsl:key name="fileByArtistYear" match="File" use="concat(@MediaArtists, '|', @MediaYear)" /> 
<xsl:key name="fileByAlbumArtistYear" match="File" use="concat(@MediaAlbum, '|', @MediaArtists, '|', @MediaYear)" /> 

<xsl:template match="/"> 

<xsl:for-each select="set:distinct(//File/@MediaYear)"> 
<xsl:sort select="." data-type="number" order="ascending"/> 
<MediaYear Year="{.}"> 
    <xsl:for-each select="set:distinct(key('fileByYear', .)/@MediaArtists)"> 
    <xsl:sort select="." data-type="text" order="ascending"/> 
    <MediaArtists Artist="{.}"> 
     <xsl:for-each select="set:distinct(key('fileByArtistYear', concat(., '|', ../@MediaYear))/@MediaAlbum)"> 
     <xsl:sort select="." data-type="text" order="ascending"/> 
     <MediaAlbum Album="{.}"> 
      <xsl:for-each select="key('fileByAlbumArtistYear', concat(., '|', ../@MediaArtists, '|', ../@MediaYear))"> 
       <xsl:copy-of select="."/> 
      </xsl:for-each> 
     </MediaAlbum> 
     </xsl:for-each> 
    </MediaArtists> 
    </xsl:for-each> 
</MediaYear> 
</xsl:for-each> 

</xsl:template> 
</xsl:stylesheet> 

需要注意的是,如果你的目錄已經一年特定的,你可以使用,爲了保存在這裏進行一些處理。

+0

您好,感謝您的回答,遺憾的是Visual Studio中似乎不能夠處理以下聲明: 的xmlns:設置= 「http://exslt.org/sets」 擴展 - element-prefixes =「set」> 我有一個關於命名空間的錯誤,所以我將使用@ polly-shaw答案來避免不必要的研究,或者您可能對此錯誤有所瞭解? 謝謝 對不起,關於多編輯我不使用Shift-Enter快捷鍵.... –

+0

@ user3123948這很奇怪。您是否嘗試將'extension-element-prefixes =「set」'更改爲'exclude-result-prefixes =「set」'?什麼是你得到的錯誤信息? –

+0

似乎我找到了一些東西:http://msdn.microsoft.com/en-us/library/ms950776.aspx –