XSLT实现按Sfromlocation/Stolocation组合键分组XML元素
XSLT 2.0 自定义键分组合并实现方案
核心规则对齐
- 处理范围:仅操作
CISDocument/Entity/Load路径下的BaseShipmentModule节点,以节点内ShipUnitModule子节点的Sfromlocation+Stolocation组合值为分组键,同组节点合并为单个BaseShipmentModule - 合并逻辑:同组内所有
Shnum、Container节点统一归集到同一个ShipUnitModule下,Sfromlocation、Stolocation仅保留组内唯一值 - 保留要求:除上述待合并节点外,其余所有节点(
Aheader、ResponseHeader、Page公共节点,Load下的LID、ccode等基础字段,全部S1节点)完整保留原有结构、顺序、内容,不受分组逻辑影响
可直接使用的实现代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:默认复制所有节点、属性、文本内容,保证非目标节点无改动 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配Load节点,处理分组逻辑,严格保留原有子节点顺序 --> <xsl:template match="CISDocument/Entity/Load"> <xsl:copy> <!-- 预分组所有BaseShipmentModule,生成合并后的节点内容 --> <xsl:variable name="shipmentGroups"> <xsl:for-each-group select="BaseShipmentModule" group-by="concat(ShipUnitModule/Sfromlocation, '||', ShipUnitModule/Stolocation)"> <group first-node-id="{generate-id(current-group()[1])}"> <merged-content> <BaseShipmentModule> <ShipUnitModule> <xsl:copy-of select="ShipUnitModule/Sfromlocation[1], ShipUnitModule/Stolocation[1], current-group()/ShipUnitModule/Shnum, current-group()/ShipUnitModule/Container"/> </ShipUnitModule> </BaseShipmentModule> </merged-content> </group> </xsl:for-each-group> </xsl:variable> <!-- 按原顺序遍历Load下所有子节点、属性 --> <xsl:for-each select="@*|node()"> <!-- 非BaseShipmentModule节点直接按原规则复制 --> <xsl:apply-templates select=".[not(self::BaseShipmentModule)]"/> <!-- BaseShipmentModule节点仅在为分组首节点时输出合并内容,其余同组节点跳过 --> <xsl:if test="self::BaseShipmentModule"> <xsl:variable name="currentNodeId" select="generate-id(.)"/> <xsl:copy-of select="$shipmentGroups/group[@first-node-id = $currentNodeId]/merged-content/BaseShipmentModule"/> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
实现说明
- 采用身份模板作为默认处理逻辑,从根源避免非目标节点丢失、属性丢失、结构错乱问题
- 分组时使用
||作为拼接分隔符,避免两个字段值直接拼接导致的键值冲突(如Sfromlocation="A"、Stolocation="BC"和Sfromlocation="AB"、Stolocation="C"不会被误判为同组) - 遍历Load子节点时严格遵循输入XML的原始顺序,即便是穿插在
BaseShipmentModule之间的S1节点、其他基础字段也不会被移位,完全满足顺序保留要求 - 同组的
Sfromlocation、Stolocation取组内首节点值即可,同组这两个字段值完全一致,符合唯一值保留要求
运行注意事项
- 本代码遵循XSLT 2.0标准,需在支持XSLT 2.0的解析器上运行(如Saxon-HE 9.x及以上版本),无法直接在仅支持XSLT 1.0的环境中使用
- 若
ShipUnitModule下存在除Sfromlocation、Stolocation、Shnum、Container外其他需要归集的字段,只需修改ShipUnitModule标签内xsl:copy-of的节点选择路径,补充对应字段即可
内容的提问来源于stack exchange,提问作者Manju Kaushik
相关产品推荐
相关产品推荐

