【问题标题】:Using XSLT to calculate start times of a video playlist使用 XSLT 计算视频播放列表的开始时间
【发布时间】:2021-12-10 18:25:34
【问题描述】:

我有以下 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::*/name]"。但它不起作用,因为如果一个视频在 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>

而 Video2 的 start_time 应该是 400。

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

【问题讨论】:

  • 如果您可以使用 XSLT 3.0,这是 xsl:iterate 指令的经典用例。对于 1.0,必须使用递归来完成。

标签: xml join xslt playlist


【解决方案1】:

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

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>

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 2023-02-22
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    相关资源
    最近更新 更多