【问题标题】:Calculating the total of a calculated column using XSLT使用 XSLT 计算计算列的总计
【发布时间】:2012-04-19 11:35:50
【问题描述】:

我今天刚学习了 XSLT,当时我想从 iTunes 中漂亮地打印播放列表导出 (xml)。我终于明白了 XSLT 与 XML 的关系以及它的用途。我从 iTunes2Html 并为我自己的目的定制了它。我创建了一个动态列,它是歌曲的播放时间/持续时间(对于设置开始和结束时间的人/djs 很有用!)。在显示结束时我想要的是所有持续时间列的总和。我不知道该怎么做。到目前为止,我已经研究了堆栈溢出和谷歌,但没有运气。我发现的结果令人困惑。

那么任何人都可以帮助我弄清楚如何计算动态/计算列的总数吗?见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>

编辑:阐明持续时间计算的逻辑。由于 start 和 stop 是可选的,因此实际公式为 (stop | total) - (start | 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>

这是输出

显示在持续时间列底部的所需输出(即所有持续时间的总和):

Total Playtime Duration - 9:43

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

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

【问题讨论】:

  • 您使用的是 XSLT2(这使得这更容易)还是 XSLT1,如果您使用的是 XSLt1,您是否有可用的节点集扩展? (或者等效地,您使用的是哪个 XSLT 处理器?)
  • 为什么“长度”与“持续时间”不同?请您解释一下“长度”是什么意思?另外,为什么其中两首曲目没有任何“开始时间”?这是什么意思?最后,为什么最后一首没有任何“停止时间”?请您提供想要的输出吗?
  • @DavidCarlisle 我正在使用 IE9 查看转换。这是根据 w3.org/1999/XSL/Transform" version='1.0'> 的 V1
  • @DimitreNovaatchev 开始和停止时间是可选的,不是必需的!长度是曲目的总长度,持续时间只是曲目的播放时间,取决于开始和停止时间。我将编辑上面的帖子以提及想要的输出
  • +1 用于提供完整的工作示例和不缺少重要细节的解释。

标签: xml xslt itunes


【解决方案1】:
<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,这是我最终使用的最终代码。我把它放在这里以供将来参考。

【讨论】:

    【解决方案2】:

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

    <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

    【讨论】:

    • 感谢您的回答,我会尝试并回复您。我以前见过这个,你必须做两次计算!那么最终的答案是您不能对 XSL 中的计算列进行操作吗?你必须重复计算?这似乎违反了DRY 原则。
    • @Vijay:这就是原版 XSLT 1.0 的结果。许多 XSLT 处理器实现的 node-set() 扩展函数允许您重复使用计算结果,但它并非在任何地方都可用。
    • 您的解决方案有效!!我只需要弄清楚放置代码的位置并稍微修改 xpath。我已经编辑了您的答案以显示我使用的实际代码。
    • @Vijay 抱歉,我已拒绝编辑。您可以将最终使用的代码放入您自己的帖子中,但它不会是我的相关补充。
    【解决方案3】:

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

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

    【讨论】:

    • 持续时间列不是原始XML文件中的节点,所以我认为无法解析它。 XSL 是否允许在它生成的文档中选择节点?我试过你说的,这也是我在研究时发现的建议,但没有运气。
    • 如果持续时间总是stop - start 为什么不将所有停止时间相加然后减去所有开始时间的总和?
    • 由于startstop是可选的,所以实际公式为(stop | total) - (start | 0)
    猜你喜欢
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 2020-06-30
    • 2022-01-27
    相关资源
    最近更新 更多