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

如何用XSLT从XML父标签与子标签取值并转换为CSV

别担心,新手刚接触XSLT时遇到这种节点层级的问题太正常啦!你的核心困扰其实是XSLT的上下文节点切换——当你用<xsl:for-each select="//PayDetails">时,当前的上下文变成了PayDetails节点,直接访问StaffNumber自然找不到,因为它在PayDetails的父节点Payslip里。

这里给你两种简单的解决思路,根据你的需求选就行:

思路1:在子节点循环中通过相对路径获取父节点数据

如果你需要以PayDetails为单位生成CSV行,可以在循环PayDetails时,用../(表示当前节点的父节点)或者ancestor::Payslip(表示向上找到最近的Payslip祖先节点)来获取StaffNumber:

修改后的XSLT示例:

<?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="/">
Worker,Pay_Group,Pay_Period_End_Date,Payment_Date,Net_Amount,Gross_Amount,Currency,Ck_Number,Display_Date
    <xsl:for-each select="//Payslip//PayDetails">
      <!-- 用../StaffNumber获取父节点Payslip下的StaffNumber -->
      <xsl:value-of select="concat(../StaffNumber,',','PAY_GROUP',',','2017-09-24-00:00',',','2017-09-27-00:00',',',AmountNet,',','AmountGross',',','AUD',',','393',',','SLP000393_',../StaffNumber,'.pdf',',','&#xA;')"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

思路2:嵌套循环,先遍历父节点再遍历子节点

如果每个Payslip下可能有多个PayDetails,想要把父节点的公共数据(比如StaffNumber)和每个子节点的独有数据(比如AmountNet)结合生成多行CSV,更推荐用嵌套循环:

<?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="/">
Worker,Pay_Group,Pay_Period_End_Date,Payment_Date,Net_Amount,Gross_Amount,Currency,Ck_Number,Display_Date
    <!-- 先循环父节点Payslip,保存上下文 -->
    <xsl:for-each select="//Payslip">
      <!-- 循环当前Payslip下的PayDetails -->
      <xsl:for-each select="PayDetails">
        <!-- 此时直接用StaffNumber就能拿到父节点的内容,因为外层循环的上下文还是Payslip -->
        <xsl:value-of select="concat(StaffNumber,',','PAY_GROUP',',','2017-09-24-00:00',',','2017-09-27-00:00',',',AmountNet,',','AmountGross',',','AUD',',','393',',','SLP000393_',StaffNumber,'.pdf',',','&#xA;')"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

这个思路更清晰,也更容易扩展——比如你之后要遍历ComponentDetails,直接在PayDetails的循环里再嵌套一层就好,还能轻松拿到StaffNumber、AmountNet和ComponentType这些跨层级的数据。

另外提个小细节:如果XML里有空标签(比如<Sex/>),你可以用normalize-space()来处理,避免CSV里出现多余的逗号,比如concat(normalize-space(Sex), ','),这样空值会变成空字符串,CSV格式更规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:36:28