如何在XSLT中格式化xs:gYearMonth与xs:gYear类型数据?
解决XSLT中处理xs:gYearMonth/xs:gYear并格式化的问题
嘿,这个需求其实很好实现——核心思路就是把xs:gYearMonth和xs:gYear类型的值补全为合法的xs:date格式,这样就能直接用format-date函数来格式化输出了。毕竟format-date只认完整的日期类型,咱们给不完整的年份/年月补个默认的日(比如当月/当年1号)就行。
具体实现步骤
我会用XSLT 2.0+的自定义函数来封装这个转换逻辑,这样可以在模板里重复调用:
<xsl:function name="my:format-partial-date" as="xs:string"> <xsl:param name="partial-date" as="xs:gYearMonth | xs:gYear"/> <!-- 根据输入类型补全为完整日期 --> <xsl:variable name="full-date" as="xs:date"> <xsl:choose> <!-- 处理xs:gYearMonth,补当月1号 --> <xsl:when test="$partial-date instance of xs:gYearMonth"> <xsl:value-of select="xs:date(concat($partial-date, '-01'))"/> </xsl:when> <!-- 处理xs:gYear,补当年1月1号 --> <xsl:when test="$partial-date instance of xs:gYear"> <xsl:value-of select="xs:date(concat($partial-date, '-01-01'))"/> </xsl:when> <!-- 异常情况处理,可选 --> <xsl:otherwise> <xsl:message terminate="no">警告:输入不是gYearMonth或gYear类型</xsl:message> <xsl:value-of select="xs:date('1970-01-01')"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- 调用format-date格式化,这里可以自定义格式 --> <xsl:value-of select="format-date($full-date, '[Y0001]-[M01]')"/> </xsl:function>
怎么使用这个函数
在你的模板里,直接传入对应的节点值就行:
<!-- 假设XML中有<publication-year>2023</publication-year>(xs:gYear类型) --> <p>发布年份:<xsl:value-of select="my:format-partial-date(publication-year)"/></p> <!-- 假设XML中有<update-month>2024-05</update-month>(xs:gYearMonth类型) --> <p>更新时间:<xsl:value-of select="my:format-partial-date(update-month)"/></p>
注意事项
- 确保你的XSLT处理器支持XSLT 2.0或更高版本(比如Saxon 9+),因为自定义函数和类型判断是2.0才有的特性。
- 格式化字符串可以根据需求调整,比如
'[Y0001]年[M01]月'就能输出“2024年05月”这种中文格式。 - 如果需要更灵活的格式,可以给函数再加一个参数,让调用者传入自定义的格式字符串:
<xsl:function name="my:format-partial-date" as="xs:string"> <xsl:param name="partial-date" as="xs:gYearMonth | xs:gYear"/> <xsl:param name="format" as="xs:string" default="[Y0001]-[M01]"/> <!-- 补全日期的逻辑不变 --> <xsl:variable name="full-date" as="xs:date">...</xsl:variable> <xsl:value-of select="format-date($full-date, $format)"/> </xsl:function>
这样调用的时候就能指定格式了:my:format-partial-date(update-month, '[M01]/[Y0001]')会输出“05/2024”。
内容的提问来源于stack exchange,提问作者Maroš Beťko
相关产品推荐
相关产品推荐

