使用XSLT计算计算列的总和

时间:2012-04-05 17:56:41

标签: xml xslt itunes

我刚刚学习了XSLT,当时我想从itunes打印播放列表导出(xml)。我终于明白了XSLT如何与XML相关以及它有多么有用。我从中获取了代码 iTunes2Html并根据自己的目的进行定制。我创建了一个动态列,它是一首歌的播放时间/持续时间(对设置开始和结束时间的人/ dj很有用!)。在显示结束时我想要的是所有持续时间列的总和。我无法弄清楚如何做到这一点。到目前为止,我已经研究过堆栈溢出和谷歌没有运气。我发现的结果令人困惑。

那么有人可以帮我弄清楚如何计算动态/计算列的总和吗?见similar question

以下是XSLT的相关部分

<td> <!-- calculating duration : formattime(end | total - start | 0), is there a simpler way to do it? -->
<xsl:variable name="totduration">
 <xsl:choose>
    <xsl:when test="string(number(following-sibling::Start_Time))='NaN'">
        <xsl:value-of select="following-sibling::Stop_Time"/>
    </xsl:when>
    <xsl:when test="string(number(following-sibling::Stop_Time))='NaN'">
        <xsl:value-of  select="number(following-sibling::Total_Time) - number(following-sibling::Start_Time)"/>
    </xsl:when>          
    <xsl:otherwise>
        <xsl:value-of  select="number(following-sibling::Stop_Time) - number(following-sibling::Start_Time)"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<!-- for the javascript approach using jquery. didn't work -->
<span class="sumData" style="display:none"> <xsl:value-of select="$totduration"/></span> 
<xsl:call-template name="formatTime">
  <xsl:with-param name="t" select="$totduration"/>
</xsl:call-template>
</td>

编辑:澄清持续时间计算的逻辑。由于启动和停止是可选的,实际公式是(停止|总) - (开始| 0)。这意味着如果两者都不存在,那么持续时间与长度相同,即它从头到尾播放!每首歌都有这个属性。但是,如果定义了其中一个节点(开始或停止),则持续时间可能与歌曲的总长度不同。

一些示例XML

  <songlist>
<song>
  <Track_ID>169</Track_ID>
  <Name>AAAAA</Name>
  <Album>AAAAA</Album>
  <Genre>AAAAA</Genre>
  <Start_Time>78000</Start_Time>
  <Stop_Time>122000</Stop_Time>
  <Total_Time>357537</Total_Time>
</song>
<song>
  <Track_ID>174</Track_ID>
  <Name>BBBBBB</Name>
  <Artist>BBBBBB</Artist>
  <Album>BBBBBB</Album>
  <Genre>BBBBBB</Genre>
  <Stop_Time>120000</Stop_Time>
  <Total_Time>275043</Total_Time>
</song>
<song>
  <Track_ID>177</Track_ID>
  <Name>CCCCCC</Name>
  <Artist>CCCCCC</Artist>
  <Album>CCCCCC</Album>
  <Genre>CCCCCC</Genre>
  <Stop_Time>62000</Stop_Time>
  <Total_Time>287738</Total_Time>
</song>
<song>
  <Track_ID>180</Track_ID>
  <Name>DDDDDDD</Name>
  <Artist>DDDDDDD</Artist>
  <Album>DDDDDDD</Album>
  <Genre>DDDDDDD</Genre>
  <Start_Time>43000</Start_Time>
  <Total_Time>400274</Total_Time>
</song>

这是输出 Screenshot

期望输出,因为它出现在持续时间列的底部(即所有持续时间的总和):

Total Playtime Duration - 9:43

还有更好的方法(如上所示)在xslt中执行此公式吗?我目前正在使用xsl:choose检查NaN并相应地使用替代方案。我不禁想到必须有更好的方法。

formattime((stop | total) - (start | 0))

3 个答案:

答案 0 :(得分:1)

这应该可以准确地为您提供所需内容:

<xsl:variable name="total" select="
  sum(song[Stop_Time &gt; 0]/Stop_Time | song[not(Stop_Time &gt; 0)]/Total_Time)
  -
  sum(song/Start_Time)
" />

对于您的XML示例,评估结果为583274,即9m, 43s

答案 1 :(得分:0)

使用xpath函数sum并使用表达式选择要求的所有节点。 例如

<xsl:value-of select="sum(/my/node)"/>

答案 2 :(得分:0)

<xsl:variable name="totalduration" select="
  sum($songs/song[Stop_Time > 0]/Stop_Time | $songs/song[not(Stop_Time > 0)]/Total_Time )
  -
  sum($songs/song/Start_Time)
" />
<p> Total Duration for playlist:   
  <xsl:call-template name="formatTime">
    <xsl:with-param name="t" select="$totalduration"/>
  </xsl:call-template>
</p>

这是我最终使用的最终代码感谢@tomalak。我把它放在这里供将来参考。