如何使用XSLT计算含重复视频的播放列表各条目的开始时间
问题原因
你的原始逻辑中,sum(/myXML/Titles/Title[name=current()/preceding-sibling::*/name]/duration)写法会自动对匹配到的Title节点去重,同一视频即使多次出现在前面的播放序列中,也只会被统计一次时长,因此得到的求和结果是错误的。
解决方案
方案1:XSLT 2.0 实现(更简洁)
直接遍历每个前面的Video节点,分别查询对应的时长后求和:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <Playlist> <xsl:for-each select="myXML/Clock/Video"> <Video> <name><xsl:value-of select="name"/></name> <start_time> <xsl:value-of select="sum( for $prev in preceding-sibling::Video return /myXML/Titles/Title[name = $prev/name]/duration )"/> </start_time> </Video> </xsl:for-each> </Playlist> </xsl:template> </xsl:stylesheet>
方案2:XSLT 1.0 实现(兼容旧版本)
因为XSLT 1.0不支持在sum中直接遍历节点序列取值,我们可以用递归模板累计计算每个视频的开始时间:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 递归模板计算累计时长 --> <xsl:template name="calcStartTime"> <xsl:param name="videoNodes"/> <xsl:param name="total" select="0"/> <xsl:choose> <xsl:when test="$videoNodes"> <xsl:variable name="currentDuration" select="/myXML/Titles/Title[name = $videoNodes[1]/name]/duration"/> <xsl:call-template name="calcStartTime"> <xsl:with-param name="videoNodes" select="$videoNodes[position() > 1]"/> <xsl:with-param name="total" select="$total + $currentDuration"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$total"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="/"> <Playlist> <xsl:for-each select="myXML/Clock/Video"> <Video> <name><xsl:value-of select="name"/></name> <start_time> <xsl:call-template name="calcStartTime"> <xsl:with-param name="videoNodes" select="preceding-sibling::Video"/> </xsl:call-template> </start_time> </Video> </xsl:for-each> </Playlist> </xsl:template> </xsl:stylesheet>
正确输出结果
<?xml version="1.0" encoding="UTF-8"?> <Playlist> <Video> <name>Video3</name> <start_time>0</start_time> </Video> <Video> <name>Video1</name> <start_time>100</start_time> </Video> <Video> <name>Video3</name> <start_time>300</start_time> </Video> <Video> <name>Video2</name> <start_time>400</start_time> </Video> </Playlist>
内容的提问来源于stack exchange,提问作者Nelibo
相关产品推荐
相关产品推荐

