You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT子节点复制至对应父节点问题求助

XSLT映射问题:匹配L24的MAT字段与ITEM的IDEN字段并移动节点

需求:编写XSLT,将ITEM段移动至对应的L24父节点(匹配L24的<MAT>字段值与ITEM的<IDEN>字段值),不匹配的ITEM段不保留。现有XSLT无法得到预期转换结果,以下是相关代码及预期效果:

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <CODI BEGIN="1">
        <L20 SEGMENT="1">
            <ELN>Value1</ELN>       
            <L24 SEGMENT="1">           
                <MAT>12345</MAT>  
                <field1>text </field1>
                <ITEM SEGMENT="1">
                    <IDEN>12345</IDEN>
                    <Fields>00</Fields>
                </ITEM>
                <ITEM SEGMENT="1">                  
                    <IDEN>45678</IDEN>
                    <Fields>10</Fields>
                </ITEM>
                <ITEM SEGMENT="1">                  
                    <IDEN>45678</IDEN>
                    <Fields>11</Fields>
                </ITEM>
                <ITEM SEGMENT="1">              
                    <IDEN>667788</IDEN>
                    <Fields>12</Fields>
                 </ITEM>
                <ITEM SEGMENT="1">                  
                    <IDEN>667788</IDEN>
                    <Fields>13</Fields>
                </ITEM>
                <ITEM SEGMENT="1">              
                    <IDEN>112233</IDEN>
                    <Fields>20</Fields>
                </ITEM>
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>          
            </L24>
            <L24 SEGMENT="1">               
                <MAT>45678</MAT>
                 <field1>text1 </field1>                
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>          
            </L24>
            
            <L24 SEGMENT="1">               
                <MAT>60987</MAT>    
                  <field1>text2 </field1>           
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
            </L24>
            <L24 SEGMENT="1">               
                <MAT>667788</MAT>   
                <field1>text3 </field1>         
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
                </L24>
            
            <L24 SEGMENT="1">
                <MAT>112233</MAT>   
                  <field1>text4 </field1>           
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
        
            </L24>
            
        </L20>
    </CODI>
</HEADER>

预期输出XML

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <CODI BEGIN="1">
        <L20 SEGMENT="1">
            <ELN>Value1</ELN>       
            <L24 SEGMENT="1">           
                <MAT>12345</MAT>
                 <field1>text </field1>
                <ITEM SEGMENT="1">
                    <IDEN>12345</IDEN>
                    <Fields>00</Fields>
                </ITEM>     
            
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>          
            </L24>
            <L24 SEGMENT="1">               
                <MAT>45678</MAT>
               <field1>text1 </field1>              
                    
              <ITEM SEGMENT="1">                    
                    <IDEN>45678</IDEN>
                    <Fields>10</Fields>
                </ITEM>
                <ITEM SEGMENT="1">                  
                    <IDEN>45678</IDEN>
                    <Fields>11</Fields>
                </ITEM> 
                              <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>          
            </L24>
            
            <L24 SEGMENT="1">               
                <MAT>60987</MAT>    
                 <field1>text2 </field1>            
                <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
            </L24>
            <L24 SEGMENT="1">               
                <MAT>667788</MAT>               
                <field1>text3 </field1>     
                    <ITEM SEGMENT="1">              
                    <IDEN>667788</IDEN>
                    <Fields>12</Fields>
                 </ITEM>
                <ITEM SEGMENT="1">                  
                    <IDEN>667788</IDEN>
                    <Fields>13</Fields>
                </ITEM>
                               <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
                </L24>
            
            <L24 SEGMENT="1">
                <MAT>112233</MAT>               
                 <field1>text4 </field1>
                    <ITEM SEGMENT="1">              
                    <IDEN>112233</IDEN>
                    <Fields>20</Fields>
                </ITEM>
                               <L19 SEGMENT="1">
                    <LF>Value2</LF>
                </L19>
        
            </L24>
            
        </L20>
    </CODI>
</HEADER>

当前使用的XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
  <xsl:key name="IDEN-by-key" match="//ITEM" use="@IDEN" />
  
  <!-- Identity template to copy all nodes as-is -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="//L24">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    
      <xsl:for-each select="('IDEN-by-key', @IDEN)">
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

问题分析与修正方案

原XSLT存在两处关键错误:

  1. 键定义错误:<xsl:key>中use="@IDEN"错误,IDEN是ITEM的子元素而非属性,应改为use="IDEN"(取元素的字符串值)。
  2. L24模板逻辑错误:原模板中的<xsl:for-each>写法完全不符合key的调用逻辑,且未过滤原有的ITEM节点,导致所有原始ITEM会被保留,同时无法正确插入匹配的节点。

修正后的XSLT如下:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
  <!-- 定义键:用ITEM的IDEN元素值作为键值 -->
  <xsl:key name="item-by-iden" match="ITEM" use="IDEN"/>
  
  <!-- 身份模板:默认复制所有节点 -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <!-- 过滤所有原始ITEM节点,避免保留多余节点 -->
  <xsl:template match="ITEM"/>
  
  <!-- 处理L24节点:在自身内容后插入匹配的ITEM -->
  <xsl:template match="L24">
    <xsl:copy>
      <!-- 复制L24自身的属性和子节点(除了ITEM) -->
      <xsl:apply-templates select="@* | node()"/>
      <!-- 查找所有IDEN等于当前L24的MAT值的ITEM,复制到当前L24下 -->
      <xsl:copy-of select="key('item-by-iden', MAT)"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

修正说明

  • 键item-by-iden正确绑定ITEM的IDEN元素值,用于快速查找匹配节点。
  • 添加match="ITEM"的模板,不输出任何内容,过滤掉所有原始的ITEM节点。
  • L24模板中,先复制自身的所有内容,再通过key()函数找到所有与当前L24的MAT值匹配的ITEM,将这些节点复制到L24节点内部,位置在原有子节点之后。

此代码可实现需求中的节点移动与匹配逻辑,输出结果与预期一致。

内容的提问来源于stack exchange,提问作者CHAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:29:49