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

XSLT 2.0中如何在for循环外部取值并替换匹配节点数据

XSLT 2.0 XML转换实现方案

源XML结构

<?xml version="1.0" encoding="UTF-8"?>
<Data>
    <set1>
        <line_data>
            <id>1</id>
            <some_data></some_data>
            <other_data></other_data>
            <allocation>
                <date>16-10-2023</date>
                <hours>1</hours>
            </allocation>
            <allocation>
                <date>23-10-2023</date>
                <hours>2</hours>
            </allocation>
            <allocation>
                <date>30-10-2023</date>
                <hours>3</hours>
            </allocation>
            <allocation>
                <date>06-11-2023</date>
                <hours>3</hours>
            </allocation>
        </line_data>
        <line_data>
           <id>2</id>
            <allocation>
                ....
            </allocation>
        </line_data>
        <line_data>
            
        </line_data>
    </set1>
    <entry>
        <id>1</id>
        <line_data>
            <week_hours>
                <start_date>23-10-2023</start_date>
                <time_hr>5</time_hr>
            </week_hours>
            <week_hours>
                <start_date>06-11-2023</start_date>
                <time_hr>10</time_hr>
            </week_hours>
        </line_data>
    </entry>
</Data>

转换需求

  • 提取set1下与entry节点中id匹配的line_data节点数据
  • 对每个allocation标签:
    • 检查entry/line_data/week_hours/start_date是否存在相同日期
    • 若存在,用week_hours的time_hr替换allocation的hours
    • 若不存在,保留原hours数据

期望输出

<?xml version="1.0" encoding="UTF-8"?>
<Data>
    <id>1</id>
    <some_data></some_data>
    <other_data></other_data>
    <allocation>
        <date>16-10-2023</date>
        <hours>1</hours>
    </allocation>
    <allocation>
        <date>23-10-2023</date>
        <hours>5</hours>
    </allocation>
    <allocation>
        <date>30-10-2023</date>
        <hours>3</hours>
    </allocation>
    <allocation>
        <date>06-11-2023</date>
        <hours>10</hours>
    </allocation>
</Data>

尝试的代码(未成功)

<xsl:variable name="vid" select="entry/id"/>
        <xsl:variable name="vExtendAppForecast" >
            <xsl:copy-of select="entry/line_data"/>
        </xsl:variable>
<xsl:for-each select=set1/line_data[id=$vid]/allocation>
<xsl:variable name="vStartDate" select="date"/>
<xsl:choose>
<xsl:when test="exists($vExtendAppForecast[week_hours/wd:start_date=$vStartDate]")
 -- replace hours with hours from variable
<xsl:when>
<xsl:otherwise>
 <xsl:copy-of select="current()"/>
<xsl:otherwise>
</choose>

正确的XSLT 2.0实现

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <!-- 建立日期与time_hr的索引,提升匹配效率 -->
    <xsl:key name="date-time-map" match="entry/line_data/week_hours" use="start_date"/>

    <xsl:template match="/Data">
        <Data>
            <!-- 获取entry中的目标ID -->
            <xsl:variable name="target-id" select="entry/id"/>
            <!-- 匹配并处理set1下对应ID的line_data子节点 -->
            <xsl:apply-templates select="set1/line_data[id = $target-id]/*"/>
        </Data>
    </xsl:template>

    <!-- 直接复制非allocation节点 -->
    <xsl:template match="line_data/*[not(self::allocation)]">
        <xsl:copy-of select="."/>
    </xsl:template>

    <!-- 处理allocation节点,替换hours逻辑 -->
    <xsl:template match="allocation">
        <allocation>
            <xsl:copy-of select="date"/>
            <hours>
                <!-- 优先使用索引匹配到的time_hr,无匹配则保留原hours -->
                <xsl:value-of select="key('date-time-map', date)/time_hr | hours"/>
            </hours>
        </allocation>
    </xsl:template>
</xsl:stylesheet>

关键说明

  1. 索引优化:用<xsl:key>建立日期到time_hr的映射,避免循环遍历查找,提升转换效率
  2. 模板匹配模式:替代for-each循环,符合XSLT的声明式编程风格,代码更简洁易维护
  3. 值替换逻辑:通过|运算符实现“有匹配则取新值,无匹配则保留原值”的逻辑,无需额外条件判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:02:15