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

如何用XSLT匹配XML节点日期,返回对应cust_Overtime_HR_ACTION元素

问题:XSLT匹配节点并追加对应元素

免责声明:我仍在学习XML/XSLT,若问题较为基础,敬请谅解。

我需要实现以下需求:在XML的A节点中查找元素,匹配B节点中的相似元素,并将B节点的对应条目返回至A节点。具体来说,找到<EmployeeTimeSheetEntry>节点下与<EmployeeTimeValuationResult>/bookingDate匹配的startDate,返回对应的<cust_Overtime_HR_ACTION>元素。

我参考相关方案尝试使用key创建查找表,但不清楚<apply-templates>语句的正确放置位置,目前编写的XSLT代码导致样式表编译报错(工具提示:无法使用提供的XML/XSL输入生成XML文档,样式表编译期间报告错误),无法理清节点检索的逻辑。


示例源XML

<EmployeeTimeSheet>
<EmployeeTimeSheet>
  <employeeTimeSheetEntry>
    <EmployeeTimeSheetEntry>
      <cust_Overtime_HR_ACTION>TOIL</cust_Overtime_HR_ACTION>
      <startDate>2024-11-25T00:00:00.000</startDate>
    </EmployeeTimeSheetEntry>
    <EmployeeTimeSheetEntry>
      <cust_Overtime_HR_ACTION>TOIL</cust_Overtime_HR_ACTION>
      <startDate>2024-11-27T00:00:00.000</startDate>
    </EmployeeTimeSheetEntry>
    <EmployeeTimeSheetEntry>
      <cust_Overtime_HR_ACTION>Payout</cust_Overtime_HR_ACTION>
      <startDate>2024-11-30T00:00:00.000</startDate>
    </EmployeeTimeSheetEntry>
  </employeeTimeSheetEntry>
  <employeeTimeValuationResult>
    <EmployeeTimeValuationResult>
      <bookingDate>2024-11-25T00:00:00.000</bookingDate>
    </EmployeeTimeValuationResult>
  </employeeTimeValuationResult>
</EmployeeTimeSheet>
</EmployeeTimeSheet>

尝试的XSLT代码(编译报错)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- generate lookup table - must be top level, i.e. before template match -->
<xsl:key name="timeSheetEntry" match="EmployeeTimeSheet/EmployeeTimeSheet/employeeTimeSheetEntry/EmployeeTimeSheetEntry" use="startDate"/>

<xsl:template match="/">

<EmployeeTimeSheet>

<!-- retrieve cust_Overtime_HR_ACTION where the bookingDate matches the startDate in above lookup -->
<xsl:template match="/">
    <xsl:apply-templates select="key('timeSheetEntry', EmployeeTimeSheet/EmployeeTimeSheet/employeeTimeValuationResult/EmployeeTimeValuationResult/bookingDate)/cust_Overtime_HR_ACTION"/>
</xsl:template>
    <xsl:for-each select="EmployeeTimeSheet/EmployeeTimeSheet">
        <xsl:for-each select="employeeTimeValuationResult/EmployeeTimeValuationResult">
            <xsl:variable name="var_TimeValResult" select="./*"></xsl:variable>
                <EmployeeTimeSheet>
                    <xsl:copy-of select="$var_TimeValResult"/>
                    
                    <xsl:template match="cust_Overtime_HR_ACTION"> 
                    <overtimeHRaction>                  
                        <xsl:value-of select="."/>
                    </overtimeHRaction> 
                    </xsl:template> 
                    
                </EmployeeTimeSheet>
            </xsl:for-each>
        </xsl:for-each>  <!-- EmployeeTimeSheet/EmployeeTimeSheet -->
</EmployeeTimeSheet> 
</xsl:template> 
</xsl:stylesheet>

期望输出

<EmployeeTimeSheet>
<EmployeeTimeSheet>
  <employeeTimeValuationResult>
    <EmployeeTimeValuationResult>
      <bookingDate>2024-11-25T00:00:00.000</bookingDate>
      <cust_Overtime_HR_ACTION>TOIL</cust_Overtime_HR_ACTION>
    </EmployeeTimeValuationResult>
  </employeeTimeValuationResult>
</EmployeeTimeSheet>
</EmployeeTimeSheet>

解决方案

错误分析

  1. 模板嵌套违规:XSLT要求所有<xsl:template>必须是<xsl:stylesheet>的直接子节点,不能嵌套在其他模板或for-each内部,这是编译报错的核心原因。
  2. key路径冗余:key的匹配模式无需写完整路径,只要能定位到目标节点即可,简化后更通用。
  3. 逻辑混乱:同时混用apply-templates和for-each,且未正确关联bookingDate与startDate的匹配逻辑,也未保留原XML的结构层级。

正确的XSLT代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <!-- 定义key:以startDate为键,匹配所有EmployeeTimeSheetEntry节点 -->
    <xsl:key name="timeSheetByDate" match="EmployeeTimeSheetEntry" use="startDate"/>

    <!-- 身份模板:复制所有未被自定义模板匹配的节点和属性 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 移除不需要保留的employeeTimeSheetEntry节点 -->
    <xsl:template match="employeeTimeSheetEntry"/>

    <!-- 为EmployeeTimeValuationResult节点追加匹配的cust_Overtime_HR_ACTION -->
    <xsl:template match="EmployeeTimeValuationResult">
        <xsl:copy>
            <!-- 复制原节点的所有内容 -->
            <xsl:apply-templates select="@*|node()"/>
            <!-- 通过key查找对应startDate等于当前bookingDate的EmployeeTimeSheetEntry,复制其cust_Overtime_HR_ACTION -->
            <xsl:copy-of select="key('timeSheetByDate', bookingDate)/cust_Overtime_HR_ACTION"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

代码说明

  1. key定义:用startDate作为索引键,匹配所有EmployeeTimeSheetEntry节点,后续可以快速通过日期查找对应节点。
  2. 身份模板:默认复制所有节点和属性,确保原XML的大部分结构被保留,不需要手动复制每个节点。
  3. 移除冗余节点:通过空模板匹配employeeTimeSheetEntry,使其不被复制到输出中,符合期望输出的结构。
  4. 追加目标元素:针对EmployeeTimeValuationResult节点,先复制原有内容,再通过key('timeSheetByDate', bookingDate)找到日期匹配的EmployeeTimeSheetEntry,复制其cust_Overtime_HR_ACTION元素追加到当前节点内。

运行该XSLT即可得到你期望的输出结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:44:55