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
</xsl:text> <xsl:for-each select="root//Payslip"> <!-- 直接筛选ID为SALARY的ComponentType下的Amount --> <xsl:apply-templates select="PayDetails/ComponentDetails/ComponentType[@ID='SALARY']/Amount"/> <xsl:text>
</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>
改动说明
- 去掉了多余的
<xsl:if>判断,直接在select属性里用[@ID='SALARY']精准定位符合条件的<ComponentType>标签,这样只会选中ID为SALARY的条目下的<Amount>。 - 简化了层级遍历,把嵌套的
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
相关产品推荐
相关产品推荐

