2013-12-20 34 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 –