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

XSLT 1.0:合并重复元素对应子元素及多文件输出需求

解决方案:XML转双CSV文件(流式输出)或合并式CSV

我来帮你搞定这个XML转CSV的需求,尤其是嵌套MatchingSubRecords的处理,先给你优先要的流式双文件方案,再补充合并到主CSV的备选方案。


一、优先方案:流式输出两个独立CSV文件

这个方案用XSLT结合exsl:document扩展,配合.NET的XslCompiledTransform实现流式写入主记录和子记录两个文件,方便后续关联分析,大XML文件也能高效处理。

1. 实现XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl">
  <xsl:output method="text" encoding="UTF-8" />
  
  <!-- 主输出:主记录CSV -->
  <xsl:template match="/Root">
    <!-- 写入主CSV表头 -->
    <xsl:text>Field1,Field2&#10;</xsl:text>
    <xsl:apply-templates select="Record" />
    
    <!-- 生成子记录CSV文件 -->
    <exsl:document href="sub_records.csv" method="text" encoding="UTF-8">
      <!-- 子CSV表头(带父级关联字段) -->
      <xsl:text>ParentField1,ParentField2,SubField1,SubField2&#10;</xsl:text>
      <xsl:apply-templates select="Record/MatchingSubRecords" mode="sub" />
    </exsl:document>
  </xsl:template>
  
  <!-- 处理主Record行 -->
  <xsl:template match="Record">
    <xsl:value-of select="Field1" />
    <xsl:text>,</xsl:text>
    <xsl:value-of select="Field2" />
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
  
  <!-- 处理子记录,携带父级关联信息 -->
  <xsl:template match="MatchingSubRecords" mode="sub">
    <xsl:value-of select="../Field1" />
    <xsl:text>,</xsl:text>
    <xsl:value-of select="../Field2" />
    <xsl:text>,</xsl:text>
    <xsl:value-of select="SubField1" />
    <xsl:text>,</xsl:text>
    <xsl:value-of select="SubField2" />
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

2. 用C#的XslCompiledTransform执行

using System;
using System.Xml;
using System.Xml.Xsl;

class Program
{
    static void Main()
    {
        XslCompiledTransform transform = new XslCompiledTransform();
        // 加载你的XSLT文件
        transform.Load("transform.xslt");
        
        // 启用扩展函数支持(exsl:document需要这个设置)
        XsltSettings settings = new XsltSettings(true, true);
        
        // 执行转换,主输出到main_records.csv,子输出由XSLT自动生成sub_records.csv
        using (XmlWriter writer = XmlWriter.Create("main_records.csv"))
        {
            transform.Transform("input.xml", settings, writer);
        }
        
        Console.WriteLine("转换完成,已生成main_records.csv和sub_records.csv");
    }
}

这个方案的优势是流式处理,无需把整个XML加载到内存,两个文件用父级字段关联,后续做数据分析也更灵活。


二、备选方案:合并子记录到主CSV

如果不需要分开文件,也可以把所有子字段合并到主CSV的一个字段里,完全匹配你给出的示例格式:ABC, DEF, "SUB01,SUB11,SUB21|SUB02,SUB12,SUB22"

1. 合并版XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8" />
  
  <xsl:template match="/Root">
    <!-- 主CSV表头 -->
    <xsl:text>Field1,Field2,MatchingSubRecords&#10;</xsl:text>
    <xsl:apply-templates select="Record" />
  </xsl:template>
  
  <xsl:template match="Record">
    <!-- 输出主字段 -->
    <xsl:value-of select="Field1" />
    <xsl:text>,</xsl:text>
    <xsl:value-of select="Field2" />
    <xsl:text>,"</xsl:text>
    
    <!-- 拼接所有SubField1的值 -->
    <xsl:for-each select="MatchingSubRecords">
      <xsl:value-of select="SubField1" />
      <xsl:if test="position() != last()">
        <xsl:text>,</xsl:text>
      </xsl:if>
    </xsl:for-each>
    <xsl:text>|</xsl:text>
    
    <!-- 拼接所有SubField2的值 -->
    <xsl:for-each select="MatchingSubRecords">
      <xsl:value-of select="SubField2" />
      <xsl:if test="position() != last()">
        <xsl:text>,</xsl:text>
      </xsl:if>
    </xsl:for-each>
    
    <xsl:text>"&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

2. 执行方式

同样用XslCompiledTransform,只需要把输出指向单个文件即可,生成的CSV每行包含主字段和合并后的子记录字段,适合需要单文件的场景。


额外提示

如果你的字段内容包含逗号、引号等特殊字符,可以在XSLT里加个转义模板,比如把字段里的双引号替换成两个双引号,确保CSV格式合法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:51:58