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

如何用XSLT处理多元素XML并转换为指定格式CSV?

XSLT Solution for XML to CSV with Variable <d> Elements

Great question! XSLT is absolutely a solid fit for this XML-to-CSV transformation—your existing code is almost there, it just misses handling the case where a <b> element has no <d> children. Let's fix that and make it match your desired output exactly.

The Problem with Your Current Stylesheet

Your current code uses <xsl:for-each select="d"> inside the match-b template, which means it only generates output lines when <d> elements exist. When a <b> (like the "third" one in your example) has no <d>s, this loop never runs, so that row gets omitted entirely.

Fixed XSLT Stylesheet

Here's the updated stylesheet that handles both scenarios (with and without <d> elements):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" encoding="iso-8859-1" />
  <xsl:strip-space elements="*" />

  <xsl:template match="a">
    <xsl:for-each select="b">
      <xsl:call-template name="process-b"/>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="process-b">
    <!-- First handle cases where there are <d> elements -->
    <xsl:for-each select="d">
      <xsl:value-of select="../@name"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="../c/@value"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="../c"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="."/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="../e"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>

    <!-- Now handle the case where there are NO <d> elements -->
    <xsl:if test="not(d)">
      <xsl:value-of select="@name"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="c/@value"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="c"/>
      <xsl:text>,</xsl:text>
      <xsl:text>,</xsl:text> <!-- Empty <d> value -->
      <xsl:value-of select="e"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Key Improvements Explained

  • Dual handling: We first loop through all <d> elements (just like your original code) to generate rows for each existing <d>. Then we add an <xsl:if test="not(d)"> block that triggers only when a <b> has no <d> children, outputting a row with an empty value in the <d> column.
  • Accessing sibling/parent data: Your original approach to use ../ to access the parent <b> element, then reference its other children (c, e) is perfectly correct in XSLT. This is how you "reach back" to get sibling node data while processing a <d> element.

Output Result

When run against your sample XML, this stylesheet will produce exactly your desired CSV:

first,C Value,C Text,D1 Text,E Text
first,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D1 Text,E Text
second,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D3 Text,E Text
third,C Value,C Text,,E Text

Why XSLT is a Good Fit Here

XSLT is designed specifically for XML transformations like this. Unlike your Python/lxml approach (which is totally valid!), XSLT lets you express the transformation logic in a declarative way that's tightly aligned with XML structure. It handles variable element counts (like the varying number of <d>s) naturally with loops and conditional checks, and it's widely supported across tools and platforms.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:15:44