XSLT按条件分组SG9节点问题排查及修正请求
XSLT分组问题排查与修正
需求是根据SG9节点下满足A_50='KAR'的A_51字段值,对所有SG9段进行分组,每组末尾添加<TNU>段,但原XSLT未得到预期结果。
输入示例
<?xml version="1.0" encoding="UTF-8"?> <INVR> <HNU_S> <FIELD1>0002</FIELD1> </HNU_S> <MGB_S> <FIELD1>2410458</FIELD1> </MGB_S> <GS2> <NODE> <FIELD2>SU</FIELD2> </NODE> </GS2> <SG9> <NIL_S> <FIELD1>4141</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KAR</A_50> <A_51>1234</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <SG9> <NIL_S> <FIELD1>43636</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KAR</A_50> <A_51>4567</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <SG9> <NIL_S> <FIELD1>65757</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KKR</A_50> <A_51>1234</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <SG9> <NIL_S> <FIELD1>14145</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KKR</A_50> <A_51>4567</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <TNU> <FIELD1>330</FIELD1> </TNU> </INVR>
预期输出示例
<?xml version="1.0" encoding="UTF-8"?> <INVR> <HNU_S> <FIELD1>0002</FIELD1> </HNU_S> <MGB_S> <FIELD1>2410458</FIELD1> </MGB_S> <GS2> <NODE> <FIELD2>SU</FIELD2> </NODE> </GS2> <group> <SG9> <NIL_S> <FIELD1>4141</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KAR</A_50> <A_51>1234</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <SG9> <NIL_S> <FIELD1>65757</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KKR</A_50> <A_51>1234</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <TNU> <FIELD1>330</FIELD1> </TNU> </group> <group> <SG9> <NIL_S> <FIELD1>43636</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KAR</A_50> <A_51>4567</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <SG9> <NIL_S> <FIELD1>14145</FIELD1> </NIL_S> <SG11> <SG14> <FFR> <C506> <A_50>KKR</A_50> <A_51>4567</A_51> </C506> </FFR> </SG14> </SG11> </SG9> <TNU> <FIELD1>330</FIELD1> </TNU> </group> </INVR>
原XSLT代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="SG9"> <G_SG9> <xsl:apply-templates select="*[not(self::SG9)]"/> <xsl:for-each-group select="SG9" group-by="/INVR/SG9/SG11/SG14/FFR/C506[A_50='KAR']/A_51"> <group> <xsl:copy-of select="current-group()"/> </group> </xsl:for-each-group> </G_SG9> </xsl:template> </xsl:stylesheet>
问题排查
原XSLT存在3个核心错误:
- 模板匹配层级错误:匹配
SG9节点后,尝试选择其内部的SG9子节点,但SG9本身没有该层级子节点,导致分组无数据。 - 分组键路径错误:使用绝对路径
/INVR/SG9/...会返回所有符合条件的A_51集合,而非当前节点对应的键值,无法实现正确分组。 - 未处理TNU节点:既没有移除原INVR下的TNU,也没有在每组末尾添加该节点。
修正后的XSLT代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes"/> <!-- 默认复制所有节点,INVR下的SG9和TNU将被自定义模板处理 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理INVR节点,重构SG9分组逻辑 --> <xsl:template match="INVR"> <xsl:copy> <!-- 复制除SG9和TNU外的所有子节点 --> <xsl:apply-templates select="@*|node()[not(self::SG9) and not(self::TNU)]"/> <!-- 提取所有KAR类型的A_51值作为分组键 --> <xsl:variable name="karKeys" select="SG9/SG11/SG14/FFR/C506[A_50='KAR']/A_51"/> <!-- 按每个KAR键分组对应SG9节点 --> <xsl:for-each select="$karKeys"> <xsl:variable name="currentKey" select="."/> <group> <!-- 复制同键的KAR类型SG9 --> <xsl:copy-of select="../../../../SG9[SG11/SG14/FFR/C506[A_50='KAR']/A_51 = $currentKey]"/> <!-- 复制同键的KKR类型SG9 --> <xsl:copy-of select="../../../../SG9[SG11/SG14/FFR/C506[A_50='KKR']/A_51 = $currentKey]"/> <!-- 添加TNU节点 --> <xsl:copy-of select="../TNU"/> </group> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
修正说明
- 调整模板匹配目标:改为匹配
INVR节点,直接控制其下SG9和TNU的处理,避免层级错误。 - 明确分组依据:提取所有
A_50='KAR'的A_51值作为分组键,确保每组对应唯一键值。 - 关联同键节点:对每个分组键,同时选取
A_50='KAR'和A_50='KKR'且A_51匹配的SG9节点,实现预期分组。 - 处理TNU节点:在每组末尾复制原TNU节点,同时移除原INVR下的TNU,避免重复。
内容的提问来源于stack exchange,提问作者Padd T
相关产品推荐
相关产品推荐

