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

XSLT代码调试求助:XML结构转换中行节点迁移不符合预期

XSLT 节点匹配与移动问题求助

我需要编写XSLT实现以下功能:

  • 匹配/parent/queryCompoundEmployeeResponse/CompoundEmployee/person/person_id_external和/parent/row/PERSON_ID_EXTERNAL的相同值,将对应的row节点剪切粘贴到匹配的CompoundEmployee节点下
  • 最终输出要移除<parent>标签,所有CompoundEmployee节点保留在<queryCompoundEmployeeResponse>标签内

输入XML

<?xml version='1.0' encoding='UTF-8'?>
<parent>
    <queryCompoundEmployeeResponse>
        <CompoundEmployee>
            <person>
                <person_id_external>100007</person_id_external>
            </person>
        </CompoundEmployee>
        <CompoundEmployee>
            <person>
                <person_id_external>100008</person_id_external>
            </person>
        </CompoundEmployee>
    </queryCompoundEmployeeResponse>
    <row>
        <PERSON_ID_EXTERNAL>100008</PERSON_ID_EXTERNAL>
        <APPLICANT_NUMBER>34</APPLICANT_NUMBER>
    </row>
    <row>
        <PERSON_ID_EXTERNAL>100007</PERSON_ID_EXTERNAL>
        <APPLICANT_NUMBER>12</APPLICANT_NUMBER>
    </row>
</parent>

预期输出XML

<?xml version='1.0' encoding='UTF-8'?>
    <queryCompoundEmployeeResponse>
        <CompoundEmployee>
            <person>
                <person_id_external>100007</person_id_external>
            </person>
            <row>
                <PERSON_ID_EXTERNAL>100007</PERSON_ID_EXTERNAL>
                <APPLICANT_NUMBER>12</APPLICANT_NUMBER>
            </row>
        </CompoundEmployee>
        <CompoundEmployee>
            <person>
                <person_id_external>100008</person_id_external>
            </person>
            <row>
                <PERSON_ID_EXTERNAL>100008</PERSON_ID_EXTERNAL>
                <APPLICANT_NUMBER>34</APPLICANT_NUMBER>
            </row>
        </CompoundEmployee>
    </queryCompoundEmployeeResponse>

当前使用的XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <!-- Identity template copies everything as is -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- Matches rows with PERSON_ID_EXTERNAL and moves them under corresponding CompoundEmployee -->
    <xsl:template match="parent/row">
        <xsl:variable name="currentId" select="PERSON_ID_EXTERNAL"/>
        <xsl:variable name="targetCompoundEmployee" select="//CompoundEmployee[person/person_id_external = $currentId]"/>
        
        <!-- Copy row content under corresponding CompoundEmployee -->
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
        
        <!-- Remove the row after moving it -->
        <xsl:apply-templates select="//row[PERSON_ID_EXTERNAL = $currentId]/following-sibling::row[1]"/>
        
        <!-- Remove empty parent tag if there are no more rows -->
        <xsl:if test="not(//row)">
            <xsl:apply-templates select="parent::node()[not(self::row)]"/>
        </xsl:if>
    </xsl:template>
    
    <!-- Matches parent and moves CompoundEmployee under queryCompoundEmployeeResponse -->
    <xsl:template match="parent">
        <xsl:apply-templates select="queryCompoundEmployeeResponse"/>
    </xsl:template>
    
</xsl:stylesheet>

问题分析与修正方案

当前代码存在逻辑混乱:直接复制row但未将其放入目标CompoundEmployee节点,同时未正确抑制原row节点输出,导致结果不符合预期。以下是修正后的代码:

修正后的XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <!-- 建立索引,快速匹配PERSON_ID_EXTERNAL对应的row节点 -->
    <xsl:key name="row-by-id" match="/parent/row" use="PERSON_ID_EXTERNAL"/>
    
    <!-- 身份模板:默认复制所有节点 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- 跳过parent节点,直接输出queryCompoundEmployeeResponse -->
    <xsl:template match="parent">
        <xsl:apply-templates select="queryCompoundEmployeeResponse"/>
    </xsl:template>
    
    <!-- 处理CompoundEmployee节点,添加匹配的row -->
    <xsl:template match="CompoundEmployee">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <!-- 根据当前节点的person_id_external查找对应row -->
            <xsl:apply-templates select="key('row-by-id', person/person_id_external)"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- 抑制原row节点的输出,实现"剪切"效果 -->
    <xsl:template match="/parent/row"/>
</xsl:stylesheet>

修正逻辑说明

  1. 索引优化:用<xsl:key>建立row节点与PERSON_ID_EXTERNAL的绑定,避免重复遍历XML,提升匹配效率
  2. 简化节点处理:直接通过parent模板输出目标容器queryCompoundEmployeeResponse,自动移除parent标签
  3. 节点插入:扩展CompoundEmployee模板,在复制自身内容后,插入匹配的row节点
  4. 原节点抑制:单独匹配/parent/row节点且不输出,确保原位置的row被"移除"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 03:58:19