使用 XSLT 计算视频播放列表的开始时间

Using XSLT to calculate start times of a video playlist

我有以下 XML 表示视频列表(标题)和使用这些视频的播放列表(时钟):

<?xml version="1.0" encoding="UTF-8"?>
<myXML>
<Titles>
    <Title>
        <name>Video1</name>
        <duration>200</duration>
    </Title>
    <Title>
        <name>Video2</name>
        <duration>300</duration>
    </Title>
    <Title>
        <name>Video3</name>
        <duration>100</duration>
    </Title>
</Titles>
<Clock>
    <Video>
        <name>Video3</name>
    </Video>
    <Video>
        <name>Video1</name>
    </Video>
    <Video>
        <name>Video3</name>
    </Video>
    <Video>
        <name>Video2</name>
    </Video>
</Clock>
</myXML>

我想使用 XSLT 创建一个新的 XML 播放列表,每个视频的顺序和 开始时间 相同(假设 Clock 中的第一个视频开始于时间 0)。可以看到,一个视频在播放列表中可以播放多次(这里Video3播放了两次)。

我试过了:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.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(/myXML/Titles/Title[name=current()/preceding-sibling::*/name]/duration)" /></start_time>
</Video>
</xsl:for-each>
</Playlist>

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

我们的想法是,对于时钟中的每个视频,计算时钟中前面视频的持续时间总和,这将是视频的开始时间,使用连接操作“[name=current() /preceding-sibling::*/名称]”。但它不起作用,因为如果一个视频在 Clocks 中播放两次(或多次),它只在总和中计算一次。 此解决方案的 XML 输出为:

<?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>300</start_time></Video>
</Playlist>

而视频 2 的 start_time 应该是 400。

我试图操纵 XSLT 但没有找到令人满意的解决方案。由于 XSLT 中缺少可变变量,我感到卡住了。你知道如何实现这一目标吗?欢迎任何帮助,谢谢。

这是您可以查看的一种方式:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="title" match="Title" use="name" />

<xsl:template match="/myXML">
    <Playlist>
        <xsl:call-template name="build-list">
            <xsl:with-param name="items" select="Clock/Video"/>
        </xsl:call-template>
    </Playlist>
</xsl:template>

<xsl:template name="build-list">
    <xsl:param name="items"/>
    <xsl:param name="start" select="0"/>
    <xsl:if test="$items">
        <xsl:variable name="name" select="$items[1]/name" />
        <Video>
            <xsl:copy-of select="$name"/>
            <start_time>
                <xsl:value-of select="$start" />
            </start_time>
        </Video>
        <!-- recursive call -->
        <xsl:call-template name="build-list">
            <xsl:with-param name="items" select="$items[position() > 1]"/>
            <xsl:with-param name="start" select="$start + key('title', $name)/duration"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

另一种选择是使用所谓的“兄弟递归”(查找)。