0

我对 XSLT 完全陌生,正在尝试转换以下 XML:

<array>
   <!-- red herring -->
   <Telop ID="t01">
      <time>0</time>
      <Sentence />
   </Telop>
   <!-- start time and label -->
   <Telop ID="t02">
      <time>14</time>
      <Sentence>Subtitle 1</Sentence>
   </Telop>
   <!-- end time -->
   <Telop ID="t03">
      <time>26</time>
      <Sentence />
   </Telop>
   <!-- start time and label -->
   <Telop ID="t04">
      <time>44</time>
      <Sentence>Subtitle 2</Sentence>
   </Telop>
   <!-- end time -->
   <Telop ID="t05">
      <time>48</time>
      <Sentence />
   </Telop>
</array>

进入以下结构,其中备用节点提供开始时间和标签,紧随其后的兄弟节点提供结束时间:

    <div>
        <p begin="00:00:14.000" end="00:00:26.000">Subtitle 1</p>
        <p begin="00:00:44.000" end="00:00:48.000">Subtitle 2</p>
    </div>

我拼凑了以下内容:

<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <div xml:lang="en" style="1">
        <xsl:for-each select="array/Telop">
            <xsl:if test="not(position() mod 2)">
                <p>
                    <xsl:attribute name="begin">
                        <xsl:value-of select="time" />
                    </xsl:attribute>
                    <xsl:attribute name="end">
                        <!-- How can I get the time from the immediate following sibling? -->
                        <xsl:value-of select="/following-sibling::time" />
                    </xsl:attribute>
                    <xsl:value-of select="Sentence" />
                </p>
            </xsl:if>
        </xsl:for-each>
    </div>
</xsl:template>

这非常接近,但我不知道如何提取紧随其后的兄弟的时间值。

4

3 回答 3

3

这个 XSLT 应该可以完成这项工作。

我冒昧地删除了“xslt:for-each”(被认为是 ucky)和“xslt:if”(可以合并)

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/array">
  <div xml:lang="en" style="1">
      <xsl:apply-templates select="Telop[not(position() mod 2)]" />    
    </div>
</xsl:template>

<xsl:template match="Telop">
  <p>
    <xsl:attribute name="begin">
      <xsl:value-of select="time" />
    </xsl:attribute>
    <xsl:attribute name="end">
      <xsl:value-of select="following-sibling::Telop[1]/time" />
    </xsl:attribute>
    <xsl:value-of select="Sentence" />
</p>

</xsl:template>
</xsl:transform>

希望这可以帮助,

于 2013-11-14T12:44:15.290 回答
1

这是一种稍微不同的方法,因为它不依赖于 的模 2 position()。相反,这条线

<xsl:for-each select="Telop[Sentence/text()]">

检查是否Sentence包含文本。至于 xsl:for-each 的丑陋,这是事实,但它仍然可以完成工作。

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="array">
  <xsl:element name="div">
     <xsl:for-each select="Telop[Sentence/text()]">
        <xsl:element name="p">
              <xsl:attribute name="begin">
                 <xsl:value-of select="./time"/>
              </xsl:attribute>
              <xsl:attribute name="end">
                 <xsl:value-of select="following-sibling::Telop[1]/time"/>
              </xsl:attribute>
              <xsl:value-of select="Sentence"/>
        </xsl:element>
     </xsl:for-each>
  </xsl:element>   
</xsl:template>

</xsl:stylesheet>
于 2013-11-14T12:48:52.843 回答
0

我确定的解决方案(感谢 Marvin 和 Mathias),包括将秒值格式化为小时:分钟:秒(在此答案的帮助下)如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/array">
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:tts="http://www.w3.org/ns/ttml#styling" xml:lang="en">
    <head>
      <styling>
            <style tts:textOutline="black 1px 0px" tts:color="white" xml:id="1" tts:textAlign="center" tts:padding="0px" tts:fontSize="16px" tts:fontFamily="Arial, Helvetica, sans-serif"/>     
        </styling>
    </head>
    <body>    
        <div xml:lang="en" style="1">
            <xsl:apply-templates select="Telop[not(position() mod 2)]" />    
        </div>
    </body>
</tt>
</xsl:template>

<xsl:template match="Telop">
    <xsl:element name="p">
        <xsl:attribute name="begin">
            <xsl:call-template name="format-time">
                <xsl:with-param name="value" select="time" />
            </xsl:call-template>
        </xsl:attribute>
        <xsl:attribute name="end">
            <xsl:call-template name="format-time">
                <xsl:with-param name="value" select="following-sibling::Telop[1]/time" />
            </xsl:call-template>
        </xsl:attribute>
        <xsl:value-of select="Sentence" />
    </xsl:element>
</xsl:template>

<xsl:template name="format-time">

    <xsl:param name="value" select="." />
    <xsl:param name="alwaysIncludeHours" select="true()" />
    <xsl:param name="includeSeconds" select="true()" />

    <xsl:if test="$value > 3600 or $alwaysIncludeHours">
        <xsl:value-of select="concat(format-number($value div 3600, '00'), ':')"/>
    </xsl:if>

    <xsl:value-of select="format-number(floor($value div 60), '00')" />

    <xsl:if test="$includeSeconds">
        <xsl:value-of select="concat(':', format-number($value mod 60, '00'))" />
    </xsl:if>
</xsl:template>

</xsl:transform>
于 2013-11-14T15:35:27.357 回答