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

XSLT中如何精准选择指定ID的ComponentType标签下的Amount值?

解决XSLT中精准筛选特定ID的ComponentType标签问题

你现在遇到的问题很典型:在处理重复的同名XML标签时,想用条件判断只选中特定ID的条目,但结果却把所有同层级的对应值都捞出来了。咱们先拆解下问题,再给你修正后的代码。

你的XML示例

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
  <PayrunDetails> 
    <PayrunNumber>000777</PayrunNumber> 
  </PayrunDetails> 
  <PayLocation> 
    <LocationCode>ACT</LocationCode> 
    <LocationDescription>ACT</LocationDescription> 
    <CompanyDetails> 
      <CName>APPLE Limited</CName> 
      <Payslip> 
        <StaffNumber>12345</StaffNumber> 
        <PayDetails> 
          <AmountGross>9999</AmountGross> 
          <ComponentDetails> 
            <ComponentType ID="SALARY"> 
              <Amount>1999</Amount> 
              <YTDAmount>10616</YTDAmount> 
            </ComponentType> 
          </ComponentDetails> 
          <ComponentDetails> 
            <ComponentType ID="TAX"> 
              <Amount>7305</Amount> 
              <YTDAmount>76703</YTDAmount> 
            </ComponentType> 
          </ComponentDetails> 
        </PayDetails> 
      </Payslip> 
    </CompanyDetails> 
  </PayLocation> 
</root>

你当前XSL代码的问题

你写的<xsl:if test="PayDetails/ComponentDetails/ComponentType/@ID='SALARY'">只是在判断当前<Payslip>下是否存在ID为SALARY的条目,但后面的<xsl:apply-templates select="PayDetails/ComponentDetails/ComponentType/Amount"/>还是会选中所有<ComponentType>下的<Amount>——完全没把ID筛选条件带到选择逻辑里,这就是为啥你同时拿到了SALARY和TAX的Amount值。

修正后的XSL代码

咱们直接把筛选条件整合到选择器里,或者在模板匹配时加上条件,两种方式都可行,这里给你最直接的修改版本:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" > 
  <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> 

  <xsl:template match="/"> 
    <xsl:text>Amount&#xA;</xsl:text> 
    <xsl:for-each select="root//Payslip"> 
      <!-- 直接筛选ID为SALARY的ComponentType下的Amount -->
      <xsl:apply-templates select="PayDetails/ComponentDetails/ComponentType[@ID='SALARY']/Amount"/> 
      <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
  </xsl:template> 

  <xsl:template match="*[contains(., ',')]"> 
    <xsl:text>"</xsl:text> 
    <xsl:value-of select="." /> 
    <xsl:text>"</xsl:text> 
  </xsl:template> 
</xsl:stylesheet>

改动说明

  1. 去掉了多余的<xsl:if>判断,直接在select属性里用[@ID='SALARY']精准定位符合条件的<ComponentType>标签,这样只会选中ID为SALARY的条目下的<Amount>。
  2. 简化了层级遍历,把嵌套的for-each合并成root//Payslip,代码更简洁易读。

如果你还是想保留if判断的写法(比如有更复杂的前置逻辑需要先判断再处理),也可以改成这样:

<xsl:if test="PayDetails/ComponentDetails/ComponentType[@ID='SALARY']">
  <xsl:apply-templates select="PayDetails/ComponentDetails/ComponentType[@ID='SALARY']/Amount"/>
</xsl:if>

这里的核心是在select里也要加上ID筛选条件,不能只在if里做判断却不限制后续的选择范围。

这样处理后,你就能只得到ID为SALARY的<Amount>值(也就是1999),不会再把TAX的7305也带出来了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:36:38