XSLT日期格式

时间:2014-04-04 16:41:56

标签: xml date xslt xpath

我在这里看过各种建议,但没有一个真正有助于解决我的问题。 由于我的XML来源,我可以通过以下三种格式接收日期;

04-04-2014(DD-MM-YYYY)
04-Apr-2014(DD-MMM-YYYY)
2014-04-04(YYYY-MM-DD)

我想有一个函数或简单命令将所有这些(除了第三个,但能够识别第三个是正确的)改为YYYY-MM-DD

我有一个很长的时间,当时/何时/何时这样做,但必须有一个更简单的方法。我目前的XSLT执行以下操作;

<xsl:choose>
    <xsl:when test="contains(date, 'Jan')">
        <xsl:value-of select="concat(substring(date,6),'-01-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Feb')">
        <xsl:value-of select="concat(substring(date,6),'-02-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Mar')">
        <xsl:value-of select="concat(substring(date,6),'-03-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Apr')">
        <xsl:value-of select="concat(substring(date,6),'-04-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'May')">
        <xsl:value-of select="concat(substring(date,6),'-05-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Jun')">
        <xsl:value-of select="concat(substring(date,6),'-06-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Jul')">
        <xsl:value-of select="concat(substring(date,6),'-07-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Aug')">
        <xsl:value-of select="concat(substring(date,6),'-08-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Sep')">
        <xsl:value-of select="concat(substring(date,6),'-09-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Oct')">
        <xsl:value-of select="concat(substring(date,6),'-10-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Nov')">
        <xsl:value-of select="concat(substring(date,6),'-11-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="contains(date, 'Dec')">
        <xsl:value-of select="concat(substring(date,6),'-12-',substring(date,1,2))" />
    </xsl:when>
    <xsl:when test="string-length($dateStart) = 2">
        <xsl:value-of select="concat(substring(date,7),'-',substring(date,4,2),'-',substring(date,1,2))" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="date"/>
    </xsl:otherwise>
</xsl:choose>

因此,这将检查日期是否包含任何月份为JAN,2月等,然后如果没有,检查第一个数字是否 - 是2个字符(DD)和格式,否则它假定它是YYYY-MM -DD已经按原样输出。

我试过了 - <xsl:value-of select = "format-dateTime(date, '[Y0001]-[MN]-[D01]')"/> 但是这抱怨说日期年份不够长(因为日期被视为日期时间,应采用格式YYYY-MM-DD

感谢Ian roberts在下面的回答中,我创建了以下内容来处理更多场景并将输出分组在一起;

<xsl:variable name="months" select="('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')" />
<xsl:analyze-string select="date" flags="x"
       regex="^(
            (\d\d)-(\d\d)-(\d\d\d\d)
          | (\d\d)-([A-Za-z]{{3}})-(\d\d\d\d)
          | (\d\d\d\d)-(\d\d)-(\d\d)
          | (\d\d\d\d)-([A-Za-z]{{3}})-(\d\d)
          | (\d\d)([A-Za-z]{{3}})(\d\d\d\d)
          | (\d\d\d\d)([A-Za-z]{{3}})(\d\d))$">
        <xsl:matching-substring>
            <xsl:value-of select="if (regex-group(4)) then concat(regex-group(4),'-',regex-group(3),'-',regex-group(2)) else ''"/>
            <xsl:value-of select="if (regex-group(7)) then concat(regex-group(7),'-',format-number(index-of($months, regex-group(6)), '00'),'-',regex-group(5)) else ''"/>
            <xsl:value-of select="if (regex-group(8)) then concat(regex-group(8),'-',regex-group(9),'-',regex-group(10)) else ''"/>
            <xsl:value-of select="if (regex-group(11)) then concat(regex-group(11),'-',format-number(index-of($months, regex-group(12)), '00'),'-',regex-group(13)) else ''"/>
            <xsl:value-of select="if (regex-group(16)) then concat(regex-group(16),'-',format-number(index-of($months, regex-group(15)), '00'),'-',regex-group(14)) else ''"/>
            <xsl:value-of select="if (regex-group(17)) then concat(regex-group(17),'-',format-number(index-of($months, regex-group(18)), '00'),'-',regex-group(19)) else ''"/>
        </xsl:matching-substring>
    </xsl:analyze-string>

3 个答案:

答案 0 :(得分:2)

由于您引用format-dateTime,您必须使用XSLT 2.0,因此您可以使用正则表达式来处理它。如果您知道您将始终拥有这三种表单中的一种,那么您可以使用analyze-string

<xsl:variable name="months" select="('Jan', 'Feb', 'Mar', 'Apr', ...)" />

<xsl:analyze-string select="date" flags="x"
   regex="^(
        (\d\d)-(\d\d)-(\d\d\d\d)
      | (\d\d)-([A-Za-z]{{3}})-(\d\d\d\d)
      | (\d\d\d\d)-(\d\d)-(\d\d))$">
  <xsl:matching-substring>
    <!-- year -->
    <xsl:value-of select="regex-group(4)"/>
    <xsl:value-of select="regex-group(7)"/>
    <xsl:value-of select="regex-group(8)"/>
    <xsl:text>-</xsl:text>
    <!-- month -->
    <xsl:value-of select="regex-group(3)"/>
    <xsl:value-of select="if (regex-group(6))
          then format-number(index-of($months, regex-group(6)), '00')
          else ''"/>
    <xsl:value-of select="regex-group(9)"/>
    <xsl:text>-</xsl:text>
    <!-- day -->
    <xsl:value-of select="regex-group(2)"/>
    <xsl:value-of select="regex-group(5)"/>
    <xsl:value-of select="regex-group(10)"/>
  </xsl:matching-substring>

</xsl:analyze-string>

您的每个示例格式都会与模式中的三个替代项中的一个完全匹配,而对于非匹配替代项的所有regex-group调用都将生成空字符串。

答案 1 :(得分:2)

这里有一个功能可以像其他答案一样使用类似的正则表达式和月份序列:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="function" exclude-result-prefixes="xs"
version="2.0">
<xsl:variable name="d1" select="'2014-04-04'"/>
<xsl:variable name="d2" select="'04-04-2014'"/>
<xsl:variable name="d3" select="'04-Apr-2014'"/>

<xsl:template match="/">
    <xsl:value-of select="f:processDate($d2,'[Y0001]-[MN]-[D01]')"/>
</xsl:template>

<xsl:function name="f:processDate">
    <xsl:param name="dateString"/>
    <xsl:param name="datePattern"/>
    <xsl:variable name="month"
        select="('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Okt','Nov','Dez')"/>
    <xsl:choose>
        <!-- this will work for d1 -->
        <xsl:when test="$dateString castable as xs:date">
            <xsl:value-of select="format-date( xs:date($dateString),$datePattern)"/>
        </xsl:when>
        <!-- d2 -->
        <xsl:when test="matches($dateString,'^(\d\d-\d\d-\d\d\d\d)$')">
            <xsl:variable name="d" select="substring($dateString,1,2)"/>
            <xsl:variable name="m" select="substring($dateString,4,2)"/>
            <xsl:variable name="y" select="substring($dateString,7,4)"/>
            <xsl:value-of select="format-date( xs:date( string-join(($y, $m, $d), '-')), $datePattern )"
            />
        </xsl:when>
        <!-- d3 -->
        <xsl:when test="some $i in $month satisfies matches($dateString,concat('^(\d\d-',$i,'-\d\d\d\d)$'))">
            <xsl:variable name="d" select="substring($dateString,1,2)"/>
            <xsl:variable name="m"
                select="format-number(index-of($month,substring($dateString,4,3)),'00')"/>
            <xsl:variable name="y" select="substring($dateString,8,4)"/>
            <xsl:value-of select="format-date( xs:date( string-join(($y, $m, $d), '-')), $datePattern )"
            />
        </xsl:when>
        <xsl:otherwise>
            <xsl:message>Unsupported dateString: <xsl:value-of select="$dateString"/></xsl:message>
            <xsl:value-of select="$dateString"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:function>

</xsl:stylesheet>

答案 2 :(得分:2)

即使在XSLT 1.0中,一旦您专注于不同格式的结构而不是内容,问题就变得相当微不足道了:

<xsl:template name="normalize-datestring">
<xsl:param name="datestring"/>
        <xsl:choose>
            <xsl:when test="string-length(substring-before($datestring, '-')) = 4">
            <!-- this is YYYY-MM-DD; copy as is -->
                <xsl:value-of select="$datestring" />
            </xsl:when>
            <xsl:when test="string-length($datestring) = 10">
            <!-- this is DD-MM-YYYY; reorder -->
                <xsl:value-of select="substring($datestring, 7, 4)" />
                <xsl:text>-</xsl:text>
                <xsl:value-of select="substring($datestring, 4, 2)" />
                <xsl:text>-</xsl:text>
                <xsl:value-of select="substring($datestring, 1, 2)" />
            </xsl:when>
            <xsl:otherwise>
            <!-- this is DD-MMM-YYYY; reorder and calculate month number-->
                <xsl:value-of select="substring($datestring, 8, 4)" />
                <xsl:text>-</xsl:text>
                <xsl:variable name="mmm" select="substring($datestring, 4, 3)" />
                <xsl:variable name="m" select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', $mmm)) div 3 + 1" />
                <xsl:value-of select="format-number($m, '00')" />
                <xsl:text>-</xsl:text>
                <xsl:value-of select="substring($datestring, 1, 2)" />
            </xsl:otherwise>
        </xsl:choose>
</xsl:template>