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

如何通过公共ID字段获取XSL循环外元素的数据

XSL关联跨节点数据的解决方案

需求说明

需要输出所有标记为updated='Y'的Earning节点,同时获取同Changes节点下Plans元素中(包含Plan、Interest_Plan子元素)对应ID的Start日期,需支持多员工、每个员工多Changes的场景。

现有XML结构

<Company><Employee_Stack_Grouped>
<Employee_Stack>
<Employee>
  <Changes sequence='0'>
    <Details>
      <EmployeeID>ABC11111</EmployeeID>
    </Details>
    <Plans>
      <Plan updated='Y'>
        <Name>Plan 1</Name>
        <Start>13/10/2023</Start>
        <ID>12345</ID>
      </Plan>
      <Plan updated='Y'>
        <Name>Plan 2</Name>
        <Start>13/10/2023</Start>
        <ID>67890</ID>
      </Plan>
      <Plan>
        <Name>Plan 3</Name>
        <Start>01/01/2023</Start>
        <ID>11111</ID>
      </Plan>
      <Interest_Plan updated='Y'>
        <Name>Plan 4</Name>
        <Start>13/10/2023</Start>
        <ID>22222</ID>
      </Interest_Plan>
    </Plans>
    <Amounts>
      <Earning  updated='Y'>
        <Amount>1000</Amount>
        <Plan>
          <ID>12345</ID>
        </Plan>
      </Earning>
      <Earning updated='Y'>
        <Amount>1000</Amount>
        <Plan>
          <ID>67890</ID>
        </Plan>
      </Earning>
      <Earning>
        <Amount>100</Amount>
        <Plan>
          <ID>11111</ID>
        </Plan>
      </Earning>
      <Earning updated='Y'>
        <Amount>5000</Amount>
        <Plan>
          <ID>22222</ID>
        </Plan>
      </Earning>
    </Amounts>
  </Changes>
</Employee>
</Employee_Stack></Employee_Stack_Grouped></Company>

现有XSL代码

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xs xsi"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"></xsl:output>
<xsl:template match="Employee_Stack_Grouped">
    <File>
        <Header>
            <Employee_Number>EMP</Employee_Number>
            <Date>Start_Date</Date>
            <Amount>Amount</Amount>
            <ID>ID</ID>
        </Header>
        <xsl:apply-templates select="Employee_Stack"/>
    </File>
</xsl:template>

<xsl:template match="Employee_Stack">
    <xsl:for-each select="Employee">
        <xsl:for-each select="Changes">
            <xsl:variable name="employeeID" select="Details/EmployeeID"/>
                <xsl:for-each select="Amounts/Earning[@updated = 'Y']">
                    <row>
                        <Employee_Number><xsl:value-of select="$employeeID"/></Employee_Number>
                        <Date></Date>
                        <Amount><xsl:value-of select="Amount"/></Amount>
                        <ID><xsl:value-of select="Plan/ID"/></ID>
                    </row>
                </xsl:for-each>
        </xsl:for-each>  
    </xsl:for-each>
</xsl:template></xsl:stylesheet>

解决思路

  1. 用键值索引(xsl:key)实现高效匹配
    每个Changes节点下的Plans是独立的(不同员工/Changes的Plan ID可能重复),在Changes节点范围内定义键,将Plan和Interest_Plan的ID作为键名,对应节点作为值,快速通过ID定位目标节点,避免重复遍历。

  2. 限定键的作用域
    利用XSLT 3.0的xsl:key属性,结合当前Changes节点上下文,确保每个Changes下的键只作用于自身的Plans元素。

  3. 在Earning遍历中关联数据
    遍历Earning时,通过当前Earning/Plan/ID的值,调用key()函数获取对应的Plan或Interest_Plan节点,提取其Start日期。

修改后的XSL代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="xs xsi"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    version="3.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <!-- 定义键:在当前Changes节点下,匹配Plan和Interest_Plan,用ID作为键值 -->
    <xsl:key name="plan-by-id" match="Plan | Interest_Plan" use="ID"/>

    <xsl:template match="Employee_Stack_Grouped">
        <File>
            <Header>
                <Employee_Number>EMP</Employee_Number>
                <Date>Start_Date</Date>
                <Amount>Amount</Amount>
                <ID>ID</ID>
            </Header>
            <xsl:apply-templates select="Employee_Stack"/>
        </File>
    </xsl:template>

    <xsl:template match="Employee_Stack">
        <xsl:for-each select="Employee/Changes">
            <xsl:variable name="current-changes" select="."/>
            <xsl:variable name="employeeID" select="Details/EmployeeID"/>
            
            <xsl:for-each select="Amounts/Earning[@updated = 'Y']">
                <xsl:variable name="plan-id" select="Plan/ID"/>
                <!-- 从当前Changes的Plans中查找对应ID的Plan或Interest_Plan -->
                <xsl:variable name="matched-plan" select="key('plan-by-id', $plan-id, $current-changes)"/>
                
                <row>
                    <Employee_Number><xsl:value-of select="$employeeID"/></Employee_Number>
                    <Date><xsl:value-of select="$matched-plan/Start"/></Date>
                    <Amount><xsl:value-of select="Amount"/></Amount>
                    <ID><xsl:value-of select="$plan-id"/></ID>
                </row>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

关键说明

  • xsl:key定义了plan-by-id键,匹配Plan和Interest_Plan节点,用ID作为索引值。
  • 遍历Changes时保存当前节点到current-changes变量,调用key()时传入该变量作为上下文,确保只查找当前Changes下的计划节点。
  • 每个Earning通过$plan-id获取对应计划节点,提取Start日期填充到Date字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:35:13