You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XSLT实现日期偏移转换?XSLT1.0与2.0方案对比

问题

需要对一份XML进行转换,修改其中的日期字段:将所有<start>节点的值设为当前DateTime,<end>节点的值设为次日日期。

源XML如下:

<?xml version="1.0" encoding="UTF-8"?>
<Publication_MarketDocument xmlns="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0">
  <period.timeInterval>
    <start>2022-09-27T22:00Z</start>
    <end>2022-09-29T22:00Z</end>
  </period.timeInterval>
  <TimeSeries>
    <Period>
      <timeInterval>
        <start>2022-09-27T22:00Z</start>
        <end>2022-09-28T22:00Z</end>
      </timeInterval>
      <resolution>PT60M</resolution>
      <Point>
        <position>1</position>
        <price.amount>323.70</price.amount>
      </Point>
      <Point>
        <position>2</position>
        <price.amount>309.91</price.amount>
      </Point>
    </Period>
  </TimeSeries>
</Publication_MarketDocument>

已编写XSLT 2.0代码实现需求:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:variable name="dateNow" select="fn:format-dateTime(fn:current-dateTime(), '[Y]-[M]-[D]T[H]:[m]Z')"/>
  <xsl:variable name="dateTomorrow" select="fn:format-dateTime(fn:current-dateTime() + xs:dayTimeDuration('P1D'), '[Y]-[M]-[D]T[H]:[m]Z')"/>
  <xsl:template match="start/text()">
    <xsl:value-of select="$dateNow"/>
  </xsl:template>
  <xsl:template match="end/text()">
    <xsl:value-of select="$dateTomorrow"/>
  </xsl:template>

</xsl:stylesheet>

最初因命名空间问题转换失败,设置默认命名空间后可正常运行,但该代码基于XSLT 2.0,无法被XSLT 1.0处理器支持。目标环境为Linux,当前使用依赖JRE的Saxon处理器可得到正确结果,但JRE对自动化测试系统部署过于臃肿,询问能否仅用XSLT 1.0实现该日期偏移转换需求?


解决方案

可以用XSLT 1.0实现,不过XSLT 1.0本身没有内置日期处理函数,需借助处理器扩展或外部传入日期参数两种方式,具体实现如下:

方式一:使用libxslt的EXSLT日期扩展(Linux常用)

Linux环境下主流的XSLT 1.0处理器libxslt支持EXSLT的date扩展函数,可直接获取当前时间并计算次日日期。

对应的XSLT 1.0代码:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:doc="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0"
    xmlns:date="http://exslt.org/dates-and-times"
    exclude-result-prefixes="date doc">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- 身份模板:复制所有未被匹配的节点 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 格式化当前时间为要求的UTC格式 -->
  <xsl:variable name="current-time" select="date:date-time()"/>
  <xsl:variable name="formatted-now">
    <xsl:value-of select="concat(
      substring($current-time, 1, 4), '-',
      substring($current-time, 6, 2), '-',
      substring($current-time, 9, 2), 'T',
      substring($current-time, 12, 2), ':',
      substring($current-time, 15, 2), 'Z'
    )"/>
  </xsl:variable>

  <!-- 计算并格式化次日UTC时间 -->
  <xsl:variable name="tomorrow-time" select="date:add($current-time, 'P1D')"/>
  <xsl:variable name="formatted-tomorrow">
    <xsl:value-of select="concat(
      substring($tomorrow-time, 1, 4), '-',
      substring($tomorrow-time, 6, 2), '-',
      substring($tomorrow-time, 9, 2), 'T',
      substring($tomorrow-time, 12, 2), ':',
      substring($tomorrow-time, 15, 2), 'Z'
    )"/>
  </xsl:variable>

  <!-- 替换所有<start>节点的文本 -->
  <xsl:template match="doc:start/text()">
    <xsl:value-of select="$formatted-now"/>
  </xsl:template>

  <!-- 替换所有<end>节点的文本 -->
  <xsl:template match="doc:end/text()">
    <xsl:value-of select="$formatted-tomorrow"/>
  </xsl:template>
</xsl:stylesheet>

使用libxslt自带的xsltproc命令执行转换:

xsltproc transform.xsl input.xml > output.xml

方式二:外部传入日期参数(无扩展依赖)

如果无法使用扩展函数,可通过Shell脚本生成当前日期和次日日期,再传入XSLT处理器,避免在XSLT中处理日期计算。

对应的XSLT 1.0代码:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:doc="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0"
    exclude-result-prefixes="doc">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- 定义外部传入的日期参数 -->
  <xsl:param name="current-date-time"/>
  <xsl:param name="tomorrow-date-time"/>

  <!-- 身份模板 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="doc:start/text()">
    <xsl:value-of select="$current-date-time"/>
  </xsl:template>

  <xsl:template match="doc:end/text()">
    <xsl:value-of select="$tomorrow-date-time"/>
  </xsl:template>
</xsl:stylesheet>

用Shell脚本生成日期并调用xsltproc:

#!/bin/bash
# 生成UTC格式的当前日期和次日日期
current=$(date -u +"%Y-%m-%dT%H:%MZ")
tomorrow=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%MZ")
# 传入参数执行转换
xsltproc --stringparam current-date-time "$current" --stringparam tomorrow-date-time "$tomorrow" transform.xsl input.xml > output.xml

内容的提问来源于stack exchange,提问作者EricBDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:30:52