如何在XSLT中合并指定XML的OpprettetTidspunkt与OpprettetKl字段,生成ISOString格式的<MSG_DATE>节点?
实现思路与XSLT解决方案
当然有可行的实现思路!核心是把OpprettetTidspunkt(带时区的日期字段)和OpprettetKl(带时区的时间字段)的有效内容拼接后,转换为标准的ISO 8601日期时间格式。下面分两种常用XSLT版本给出具体实现方案:
方案1:XSLT 2.0及以上(推荐,支持原生日期时间处理)
XSLT 2.0+内置了xs:dateTime类型和格式化函数,能轻松完成日期时间的解析、合并与标准化,还能自动校验格式合法性:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://NEXSTEP.Schemas.NexstepTypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="ns2 xs"> <xsl:output method="xml" indent="yes"/> <!-- 匹配根节点,保留原有结构 --> <xsl:template match="/ns3:Bonger"> <xsl:copy> <xsl:apply-templates select="ROUTE_RECORD"/> <xsl:apply-templates select="MESSAGE_RECORD"/> </xsl:copy> </xsl:template> <!-- 处理MESSAGE_RECORD,替换原日期时间节点为合并后的MSG_DATE --> <xsl:template match="MESSAGE_RECORD"> <MESSAGE_RECORD> <InsertChange> <Message> <!-- 拼接日期和时间的核心部分,转换为标准dateTime类型 --> <xsl:variable name="combinedDateTime" as="xs:dateTime"> <xsl:value-of select="concat( substring-before(Message/ns2:OpprettetEndretSlettet/ns2:OpprettetTidspunkt, '+'), 'T', substring-before(Message/ns2:OpprettetEndretSlettet/ns2:OpprettetKl, '+') )"/> </xsl:variable> <!-- 输出指定格式的ISO字符串,按需调整可保留时区 --> <MSG_DATE> <xsl:value-of select="format-dateTime($combinedDateTime, '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01].[f001]')"/> </MSG_DATE> </Message> </InsertChange> </MESSAGE_RECORD> </xsl:template> <!-- 默认模板:保留所有未特殊处理的节点和属性 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明:
- 用
substring-before剔除两个字段的时区偏移部分(如果需要保留时区,直接拼接完整字段值即可,比如concat(OpprettetTidspunkt, 'T', substring-after(OpprettetKl, '+'))) format-dateTime函数可以精准控制输出格式,完全匹配你需要的YYYY-MM-DDTHH:MM:SS.sss样式
方案2:XSLT 1.0(无原生日期类型,纯字符串处理)
如果只能使用XSLT 1.0,通过字符串截取和拼接也能实现需求,前提是输入的日期时间格式固定:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://NEXSTEP.Schemas.NexstepTypes" exclude-result-prefixes="ns2"> <xsl:output method="xml" indent="yes"/> <!-- 根节点模板 --> <xsl:template match="/ns3:Bonger"> <xsl:copy> <xsl:apply-templates select="ROUTE_RECORD"/> <xsl:apply-templates select="MESSAGE_RECORD"/> </xsl:copy> </xsl:template> <!-- 处理MESSAGE_RECORD节点 --> <xsl:template match="MESSAGE_RECORD"> <MESSAGE_RECORD> <InsertChange> <Message> <xsl:variable name="date" select="Message/ns2:OpprettetEndretSlettet/ns2:OpprettetTidspunkt"/> <xsl:variable name="time" select="Message/ns2:OpprettetEndretSlettet/ns2:OpprettetKl"/> <!-- 截取日期核心部分,拼接T和时间核心部分 --> <MSG_DATE> <xsl:value-of select="concat( substring($date, 1, 10), 'T', substring($time, 1, string-length($time) - 6) )"/> </MSG_DATE> </Message> </InsertChange> </MESSAGE_RECORD> </xsl:template> <!-- 默认模板:保留其他节点结构 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明:
- 假设输入日期格式固定为
YYYY-MM-DD+HH:MM,时间格式固定为HH:MM:SS.sss+HH:MM substring($date,1,10)提取纯日期部分,substring($time,1,string-length($time)-6)剔除最后的时区偏移(+02:00共6个字符)
两种方案都能输出你需要的<MSG_DATE>2021-08-09T15:13:14.636</MSG_DATE>格式,若需保留时区偏移,调整拼接逻辑即可生成带时区的标准ISO字符串。
内容的提问来源于stack exchange,提问作者Shanka Somasiri
相关产品推荐
相关产品推荐

