Преобразуйте формат времени «ЧЧ: ММ: СС.ССС» в миллисекунды, используя tokenize и / или analysis-string () в xslt 1.0. - PullRequest
0 голосов
/ 19 января 2020

Я хочу преобразовать формат времени, такой как «ЧЧ: ММ: СС.SSS», в миллисекунды, используя tokenize и / или analysis-string () с XSLT 1.0.

Следующая таблица стилей xsl:

 <?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:pc="https://purl.org/net/hbuschme/teaching/2019ws-infostruk/podcast/0.3" 
    xmlns:pt="https://purl.org/net/hbuschme/teaching/2019ws-infostruk/podcast-transcript/0.1" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="exsl">
    <xsl:output method="xhtml"/>






    <xsl:template match="pc:podcast">
            <html>
                <body>
                    <h1>Episoden des Podcasts <i><xsl:value-of select="pc:title"/></i></h1>
                    <xsl:apply-templates select="pc:episode"/>
                </body>
            </html>
        </xsl:template>


        <xsl:template match="pc:episode">
            <p>
                   Episode <xsl:value-of select="@episode"/> <xsl:text> </xsl:text> <xsl:number format="1. "/> 
                               <xsl:text></xsl:text>
                               <b><xsl:value-of select="@title"/></b> <br/> 
                               <xsl:value-of select="pt:transcript"/>
                               <xsl:for-each select="pc:chapter"><ul>
                                <xsl:number count="pc:episode|pc:chapter" level="multiple" format="1.1. "/>
                                <xsl:value-of select="@title" />
                               </ul></xsl:for-each>  
                               <xsl:for-each select="@url">
                                 <xsl:sort select="@episode" order="descending" /><a href="{@url}"><xsl:apply-templates/></a>
                               </xsl:for-each>
                               <xsl:call-template name="time-to-milliseconds">
                                 <xsl:with-param name="time" select="@duration"/>
                               </xsl:call-template>

                               <xsl:call-template name="mt">
                                 <xsl:with-param name="time" select="@duration"/>
                               </xsl:call-template>
            </p>
      </xsl:template>

      <xsl:template name="time-to-milliseconds">
        <xsl:param name="time"/>
        <xsl:param name="h" select="substring-before($time, ':')"/>
        <xsl:param name="m" select="substring-before(substring-after($time,':'),':')"/>
        <xsl:param name="s" select="substring-after(substring-after($time,':'),':')"/>  
        <xsl:choose>
         <xsl:when test="contains($h, '00')">
            <xsl:value-of select="1000*(60*$m + $s)"/>
        </xsl:when>
         <xsl:otherwise>
          <xsl:value-of select="1000*(3600*$h + 60*$m + $s)"/>
         </xsl:otherwise>
          <xsl:when test="contains($m, '00')">
            <xsl:value-of select="1000*(3600*$h + $s)"/>
          </xsl:when>
          <xsl:otherwise>
          <xsl:value-of select="1000*(3600*$h + 60*$m + $s)"/>
         </xsl:otherwise>
         <xsl:when test="contains($s, '00')">
            <xsl:value-of select="1000*(3600*$h + 60*$m)"/>
          </xsl:when>
          <xsl:otherwise>
          <xsl:value-of select="1000*(3600*$h + 60*$m + $s)"/>
         </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="mt">
        <xsl:param name="time"/>
        <xsl:param name="h" select="floor($time div 3600000)"/>
        <xsl:param name="m" select="floor($time mod 3600000 div 60000)"/>
        <xsl:param name="s" select="floor($time mod 60000 div 1000)"/>
        <xsl:value-of select="concat($h,':',$m,':',$s,':')"/>
    </xsl:template>

    </xsl:stylesheet>

Ожидаемый результат:

00:42 -> 4200

Любой совет? Я не знаю, как или я могу даже использовать функцию анализа строки в XSLT 1.0. Можете ли вы дать мне пример того, как решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 20 января 2020

Это может быть немного утомительно, но все еще тривиально в чистом XSLT 1.0:

<xsl:template name="time-to-milliseconds">
    <xsl:param name="time"/>
    <xsl:param name="h" select="substring-before($time, ':')"/>
    <xsl:param name="m" select="substring-before(substring-after($time,':'),':')"/>
    <xsl:param name="s" select="substring-after(substring-after($time,':'),':')"/>  
    <xsl:value-of select="1000*(3600*$h + 60*$m + $s)"/>
</xsl:template>

Демонстрация: https://xsltfiddle.liberty-development.net/6rexjhN


Чтобы конвертировать в обратном направлении, вы можете использовать:

<xsl:template name="milliseconds-to-time">
    <xsl:param name="milliseconds"/>
    <xsl:variable name="h" select="floor($milliseconds div 3600000)"/>
    <xsl:variable name="m" select="floor($milliseconds div 60000) mod 60"/>
    <xsl:variable name="s" select="$milliseconds mod 60000 div 1000"/>
    <xsl:value-of select="format-number($h, '00')" />
    <xsl:value-of select="format-number($m, ':00')" />
    <xsl:value-of select="format-number($s, ':00.###')" />
</xsl:template>
0 голосов
/ 19 января 2020

Один из способов сделать это, учитывая XSLT 3.0, состоит в том, чтобы просто взять все ваше выражение и обернуть его в атрибут выбора XSLT, но с корректировкой кавычек типа «один-против-двойных», например,

<xsl:variable name="result" select='
 let
    $duration := string(/test/@duration),
    $components := analyze-string(
            $duration, 
            "(((\d*):)?([0-5]?[0-9]):)?([0-5]?[0-9])(\.([0-9]?[0-9]?[0-9]?))?"
        ),
    $hours := $components//fn:group[@nr="3"]/text(),
    $hours := if ($hours != "") then $hours else 0,
    $minutes := $components//fn:group[@nr="4"]/text(),
    $minutes := if ($minutes != "") then $minutes else 0,
    $seconds := $components//fn:group[@nr="5"]/text(),
    $seconds := if ($seconds != "") then $seconds else 0,
    $millis := $components//fn:group[@nr="7"]/text(),
    $millis := if ($millis != "") then $millis else 0
return
    xs:int($hours * 60 * 60 * 1000
    + $minutes * 60 * 1000
    + $seconds * 1000
    + $millis)'/>

Другой способ - переписать его, используя конструкции XSLT на более мелком уровне:

<xsl:variable name="duration" select="string(/test/@duration)"/>
<xsl:variable name="components" select='analyze-string(
            $duration, 
            "(((\d*):)?([0-5]?[0-9]):)?([0-5]?[0-9])(\.([0-9]?[0-9]?[0-9]?))?"
        )'/>
<xsl:variable name="hours" select="$components//fn:group[@nr='3']/text()'/>

et c

Третий способ - заменить вызов на fn:analyze-string() чем-то который использует инструкцию XSLT xsl:analyze-string; тогда у вас потенциально будет что-то, что работает под XSLT 2.0.

...