XSLT:当Sum节点存在有效值时分组拼接Time节点内容
XSLT 1.0 实现节点分组拼接
需要在XSLT 1.0环境下处理输入XML的
输入XML
<root> <row> <Time>Debit</Time> <Sum>(874,516.25)</Sum> </row> <row> <Time>TMU/2023/1059 A</Time> <Sum></Sum> </row> <row> <Time>TMU/2023/1019 A</Time> <Sum></Sum> </row> <row> <Time>TMU/2023/1020 A</Time> <Sum></Sum> </row> <row> <Time>Debit</Time> <Sum>(664,297.52)</Sum> </row> <row> <Time>56011846 A</Time> <Sum></Sum> </row> </root>
当前使用的XSLT代码(存在问题)
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- recursive named template --> <xsl:template name="hm"> <xsl:param name="amount"/> <xsl:param name="pos"/> <xsl:for-each select="../row"> <xsl:if test="$amount = Sum and $pos = position()"></xsl:if> <xsl:choose> <xsl:when test="string-length(Sum) > 0"> <xsl:value-of select="Time"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="', '"/> <xsl:value-of select="Time"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <Reference> <xsl:call-template name="hm"> <xsl:with-param name="amount" select="Sum"/> <xsl:with-param name="pos" select="position()"/> </xsl:call-template> </Reference> </Payment> </xsl:if> </xsl:for-each> </Trailer> </xsl:template> </xsl:stylesheet>
当前错误输出
<Trailer> <Payment> <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A, Debit,56011846 A </Reference> </Payment> <Payment> <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A, Debit,56011846 A </Reference> </Payment> </Trailer>
期望输出
<Trailer> <Payment> <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A </Reference> </Payment> <Payment> <Reference> Debit,56011846 A </Reference> </Payment> </Trailer>
修正后的XSLT代码
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配根节点,输出Trailer容器 --> <xsl:template match="/root"> <Trailer> <!-- 仅处理包含有效Sum的row节点(作为分组起始) --> <xsl:apply-templates select="row[string-length(Sum) > 0]"/> </Trailer> </xsl:template> <!-- 处理每个分组起始的row节点 --> <xsl:template match="row[string-length(Sum) > 0]"> <Payment> <Reference> <!-- 输出当前row的Time --> <xsl:value-of select="Time"/> <!-- 递归拼接后续的空Sum row的Time,直到遇到下一个有效Sum row --> <xsl:call-template name="collect-following-times"> <xsl:with-param name="current-node" select="following-sibling::row[1]"/> </xsl:call-template> </Reference> </Payment> </xsl:template> <!-- 递归收集后续空Sum row的Time --> <xsl:template name="collect-following-times"> <xsl:param name="current-node"/> <!-- 判断当前节点存在且Sum为空 --> <xsl:if test="$current-node and string-length($current-node/Sum) = 0"> <xsl:value-of select="concat(', ', $current-node/Time)"/> <!-- 递归处理下一个兄弟节点 --> <xsl:call-template name="collect-following-times"> <xsl:with-param name="current-node" select="$current-node/following-sibling::row[1]"/> </xsl:call-template> </xsl:if> </xsl:template> <!-- 忽略其他非目标节点 --> <xsl:template match="text()"/> </xsl:stylesheet>
代码说明
- 分组逻辑:以含有效
Sum的row为分组起点,仅对这些节点应用模板,确保每个分组对应一个Payment节点。 - 递归收集:通过
collect-following-times模板递归遍历当前起始节点的后续兄弟节点,仅拼接Sum为空的row的Time内容,直到遇到下一个含有效Sum的row或节点结束。 - 输出控制:直接从起始节点的
Time开始,后续每个符合条件的Time前添加,分隔符,避免多余分隔符。
内容的提问来源于stack exchange,提问作者OyeRep
相关产品推荐
相关产品推荐

