如何使用XSLT按双元素值匹配规则分组XML元素
XSLT双字段匹配分组归并实现方案
原有代码问题说明
原有实现无法达到预期的核心原因有两点:
- 分组匹配路径错误:直接在当前节点下查找
Shipment子节点,但实际Shipment是ShipmentLeg的子节点,路径不匹配导致分组逻辑无法正确命中目标节点 - 节点复制逻辑覆盖范围过大:用通用模板拦截了所有节点的复制逻辑,既没有保留
ShipmentLeg外层标签结构,也会破坏SystemLoadID、Stop等不需要分组的节点的原有输出
正确实现代码
以下XSLT 3.0代码可完全匹配预期输出结构,注意将代码中ns1对应的命名空间URI替换为你实际业务XML中ns1绑定的真实地址即可:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="替换为你的ns1实际命名空间URI"> <!-- 身份复制模板:所有无特殊处理规则的节点、属性、文本原样输出 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 针对Load节点单独处理,在这一层完成Shipment分组归并 --> <xsl:template match="ns1:Load"> <xsl:copy> <!-- 先原样输出Load下所有非ShipmentLeg的节点:如SystemLoadID、Stop节点 --> <xsl:apply-templates select="*[not(self::ns1:ShipmentLeg)]"/> <!-- 按ShipFromLocationCode + ShipToLocationCode双字段组合为key分组 --> <xsl:for-each-group select="ns1:ShipmentLeg/ns1:Shipment" group-by="concat(ns1:ShipFromLocationCode, '|', ns1:ShipToLocationCode)"> <ns1:ShipmentLeg> <ns1:Shipment> <!-- 复制Shipment固定字段 --> <xsl:copy-of select="ns1:ShipFromLocationCode, ns1:ShipToLocationCode"/> <!-- 归并同组所有Container下的内容到同一个Container节点 --> <ns1:Container> <xsl:copy-of select="current-group()/ns1:Container/*"/> </ns1:Container> </ns1:Shipment> </ns1:ShipmentLeg> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet>
实现逻辑说明
- 基础身份复制模板保证所有不需要参与分组的节点完全保留原有结构、顺序和内容,不会出现节点丢失或格式错乱
- 分组逻辑直接在
ns1:Load层执行,跨ShipmentLeg拉取所有Shipment节点做分组,不受单条ShipmentLeg的层级限制 - 每个分组生成独立的
ShipmentLeg外层标签,同组下所有Container的子节点(即示例中的SystemContainerID)会被统一归并到同一个Container节点下,和预期输出结构完全对齐 - 完整保留原XML的ns1命名空间前缀,输出格式符合原XML的命名规范
内容的提问来源于stack exchange,提问作者RvJ ADiThYA
相关产品推荐
相关产品推荐

