使用 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>
另一种选择是使用所谓的“兄弟递归”(查找)。
我有以下 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>
另一种选择是使用所谓的“兄弟递归”(查找)。