在XSLT 1.0中格式化24小时时间的最佳方法是什么?

时间:2020-03-06 14:48:47  来源:igfitidea点击:

我一直很难找到采用时间格式并轻松确定其是否有效的好方法,然后使用XSLT 1.0生成具有某种格式的结果元素。

给定以下xml:

<root>
    <srcTime>2300</srcTime>
</root>

产生生成的xml会很棒:

<root>
    <dstTime>23:00</dstTime>
</root>

但是,如果源xml包含无效的24小时制,则结果dstTime元素应为空白。

例如,当无效的源xml是以下内容时:

<root>
    <srcTime>NOON</srcTime>
</root>

生成的xml应该是:

<root>
    <dstTime></dstTime>
</root>

问题是,可以编写出最佳结果的最佳XSLT 1.0片段是什么?希望可以使其保持非常简单,而不必每次都解析(例如,如果可能的话,模式匹配会很不错)。

解决方案

XSLT 1.0没有对日期/时间操作的任何标准支持。

我们必须编写一个简单的解析和格式化功能。这将不会很简单,也不会变得很漂亮。

XSLT实际上是为树转换而设计的。最好在XSLT之外完成这种文本节点操作。

看一下:
http://www.exslt.org/特别是"日期和时间"部分。
我没有深入研究它,但是看起来它可能正是我们想要的。

甚至exslt.org time()函数也无法为我们提供帮助,因为它希望输入的格式正确(xs:dateTime或者xs:time)。

这是最好在XSLT之外解决的问题。我说这是一个经常使用XSLT来做并非真正为之设计的事情并且设法使事情起作用的人。它实际上并非旨在分析字符串。

理想的解决方案是修复生成XML文档的所有内容,以便使用为此目的而方便地建立的国际标准来格式化时间,并应遵循以下原则:如果可以避免的话,则不应该保留或者传输废话数据。

但是,如果那不可能,则应该在将数据传递给XSLT之前对其进行修复,或者在生成转换的输出之后对其进行修复。

XSLT 1.0中没有任何正则表达式,因此,恐怕模式匹配将无法实现。

我不清楚&lt;srcTime> 23:00 &lt;/ srcTime>是否合法?如果是这样,请尝试:

<dstTime>
  <xsl:if test="string-length(srcTime) = 4 or
                string-length(srcTime) = 5">
    <xsl:variable name="hour" select="substring(srcTime, 1, 2)" />
    <xsl:if test="$hour >= 0 and 24 > $hour">
      <xsl:variable name="minute">
        <xsl:choose>
          <xsl:when test="string-length(srcTime) = 5 and
                          substring(srcTime, 3, 1) = ':'">
            <xsl:value-of select="substring(srcTime, 4, 2)" />
          </xsl:when>
          <xsl:when test="string-length(srcTime) = 4">
            <xsl:value-of select="substring(srcTime, 3, 2)" />
          </xsl:when>
        </xsl:choose>
      </xsl:variable>
      <xsl:if test="$minute >= 0 and 60 > $minute">
        <xsl:value-of select="concat($hour, ':', $minute)" />
      </xsl:if>
    </xsl:if>
  </xsl:if>
</dstTime>

如果不是,那么只有四位数是合法的,那么:

<dstTime>
  <xsl:if test="string-length(srcTime) = 4">
    <xsl:variable name="hour" select="substring(srcTime, 1, 2)" />
    <xsl:if test="$hour >= 0 and 24 > $hour">
      <xsl:variable name="minute" select="substring(srcTime, 3, 2)" />
      <xsl:if test="$minute >= 0 and 60 > $minute">
        <xsl:value-of select="concat($hour, ':', $minute)" />
      </xsl:if>
    </xsl:if>
  </xsl:if>
</dstTime>

根据实际使用的xslt处理器,我们可以在自定义扩展功能中进行所需的操作(我们必须自己做)。

Xalan对扩展功能有很好的支持,我们不仅可以用Java编写它们,还可以用JavaScript或者Apache BSF支持的其他语言编写它们。

Microsoft的XSLT引擎也支持自定义扩展,如.NET Framework开发人员指南,扩展XSLT样式表中所述

为了使列表完整,Steve Ball还提供了XSLT标准库的日期/时间处理模块部分。