XSL对比斜杠格式日期报错,xs:date及format-date失效问题求助
斜杠格式日期XSLT对比失败解决方案
问题根因
xs:date() 函数仅支持 ISO 8601 标准格式(yyyy-MM-dd)的字符串转换,你当前使用的 MM/dd/yyyy 斜杠格式字符串无法直接被识别为合法日期类型,转换失败后变量会保留原始字符串类型,和日期/数值类型做对比时就会抛出类型不匹配错误。
解决方案
XSLT 2.0 及以上版本(推荐)
通过自定义函数统一将斜杠格式的日期转换为标准格式后再做对比:
<!-- 确保根节点已声明xs命名空间:xmlns:xs="http://www.w3.org/2001/XMLSchema" --> <xsl:template match="/"> <!-- 自定义转换函数:输入MM/dd/yyyy格式字符串,输出xs:date类型 --> <xsl:function name="local:parseSlashDate" as="xs:date"> <xsl:param name="dateStr" as="xs:string"/> <!-- 按/拆分日期为月、日、年三部分 --> <xsl:variable name="dateParts" select="tokenize(normalize-space($dateStr), '/')"/> <!-- 拼接为yyyy-MM-dd标准格式,个位数月日补前导零 --> <xsl:sequence select="xs:date(concat( $dateParts[3], '-', format-number(number($dateParts[1]), '00'), '-', format-number(number($dateParts[2]), '00') ))"/> </xsl:function> <!-- 替换原有变量定义 --> <xsl:variable name="ShortDate" select="local:parseSlashDate('2/15/2022')"/> <xsl:variable name="RenewalDate" select="local:parseSlashDate(renewalDate)"/> <!-- 日期对比逻辑,两个变量都是xs:date类型可直接比较 --> <xsl:if test="$RenewalDate >= $ShortDate"> <xsl:text>Date Expired</xsl:text> </xsl:if> </xsl:template>
XSLT 1.0 版本适配
如果使用不支持自定义函数和tokenize的1.0版本,可以通过字符串截取的方式实现转换:
<xsl:template match="/"> <!-- 转换ShortDate --> <xsl:variable name="shortDateStr" select="'2/15/2022'"/> <xsl:variable name="shortMonth" select="substring-before($shortDateStr, '/')"/> <xsl:variable name="shortDayYear" select="substring-after($shortDateStr, '/')"/> <xsl:variable name="shortDay" select="substring-before($shortDayYear, '/')"/> <xsl:variable name="shortYear" select="substring-after($shortDayYear, '/')"/> <xsl:variable name="ShortDate" select="concat($shortYear, '-', format-number($shortMonth, '00'), '-', format-number($shortDay, '00'))"/> <!-- 转换RenewalDate --> <xsl:variable name="renewalDateStr" select="normalize-space(renewalDate)"/> <xsl:variable name="renewalMonth" select="substring-before($renewalDateStr, '/')"/> <xsl:variable name="renewalDayYear" select="substring-after($renewalDateStr, '/')"/> <xsl:variable name="renewalDay" select="substring-before($renewalDayYear, '/')"/> <xsl:variable name="renewalYear" select="substring-after($renewalDayYear, '/')"/> <xsl:variable name="RenewalDate" select="concat($renewalYear, '-', format-number($renewalMonth, '00'), '-', format-number($renewalDay, '00'))"/> <!-- 字符串格式的标准日期可直接按字典序对比 --> <xsl:if test="$RenewalDate >= $ShortDate"> <xsl:text>Date Expired</xsl:text> </xsl:if> </xsl:template>
注意事项
- 使用
normalize-space处理从XML节点取到的日期值,避免节点前后的空白字符导致拆分失败 - 补前导零的操作不可省略,否则个位数的月份/日期会不符合格式要求,导致转换失败或者对比结果出错
内容的提问来源于stack exchange,提问作者User501
相关产品推荐
相关产品推荐

