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

如何使用Saxon XSLT将多节点XML转换为CSV字符串?

使用Saxon XSLT将XML转换为CSV字符串的完整实现

我最近在折腾用Saxon把包含多个员工节点的XML转成CSV格式的字符串,环境已经搭好了,但卡在了实际转换的步骤上——尤其是XML里的employee内部元素顺序还可能不固定,得保证数据提取准确。下面是我整理的完整解决方案,包含正确的XSLT编写和Java代码完善:

待转换的XML示例

<employees stage="test">
  <employee>
    <details>
      <name>Joe</name>
      <age>34</age>
    </details>
    <address>
      <street>test</street>
      <nr>12</nr>
    </address>
  </employee>
  <employee>
    <address>
      <street>main</street>
      <nr>45</nr>
    </address>
    <details>
      <!-- 注意元素顺序已更改! -->
      <age>24</age>
      <name>Sam</name>
    </details>
  </employee>
</employees>

编写正确的XSLT转换规则

因为XML里的name和age嵌套在details节点下,street和nr在address节点下,还要提取根节点的stage属性,同时要处理换行和逗号分隔。这里用XSLT 3.0实现,不管employee内部子节点顺序都能正确提取数据:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 输出纯文本,省略XML声明 -->
  <xsl:output method="text" omit-xml-declaration="yes"/>

  <!-- 匹配根节点,遍历所有employee -->
  <xsl:template match="/employees">
    <!-- 可选:如果需要表头可以放开下面这行 -->
    <!-- <xsl:text>stage,name,age,street,nr&#10;</xsl:text> -->
    <xsl:apply-templates select="employee"/>
  </xsl:template>

  <!-- 匹配单个employee节点,拼接CSV行 -->
  <xsl:template match="employee">
    <!-- 提取根节点的stage属性 -->
    <xsl:value-of select="../@stage"/>
    <xsl:text>,</xsl:text>
    <!-- 提取details中的name(不管内部顺序) -->
    <xsl:value-of select="details/name"/>
    <xsl:text>,</xsl:text>
    <!-- 提取details中的age -->
    <xsl:value-of select="details/age"/>
    <xsl:text>,</xsl:text>
    <!-- 提取address中的street -->
    <xsl:value-of select="address/street"/>
    <xsl:text>,</xsl:text>
    <!-- 提取address中的nr,最后加换行符 -->
    <xsl:value-of select="address/nr"/>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:transform>

说明:通过明确的节点路径提取数据,即使details内部的name和age顺序调换,也不会影响结果;如果某个节点缺失,会自动输出空值(保留逗号),符合CSV格式规范。

完善Saxon Java代码

原来的代码只完成了环境初始化,缺少核心的转换执行和结果获取步骤,下面是完整可运行的代码:

import net.sf.saxon.Processor;
import net.sf.saxon.s9api.*;

import java.io.StringWriter;

public class SaxonXmlToCsv {
    public static void main(String[] args) throws SaxonApiException {
        // 初始化Saxon处理器,false表示无需商业版功能
        Processor processor = new Processor(false);
        XsltCompiler compiler = processor.newXsltCompiler();

        // 编译指定的XSLT文件
        XsltExecutable executable = compiler.compile(new StreamSource("transformation.xslt"));

        // 创建XSLT转换执行器
        XsltTransformer transformer = executable.load();

        // 设置待转换的XML源文件路径
        transformer.setSource(new StreamSource("employees.xml"));

        // 创建StringWriter接收转换后的CSV字符串
        StringWriter writer = new StringWriter();
        Serializer serializer = processor.newSerializer(writer);

        // 配置序列化属性:避免XML声明、设置UTF-8编码防乱码
        serializer.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
        serializer.setOutputProperty(Serializer.Property.ENCODING, "UTF-8");

        // 关联转换器与序列化器,执行转换
        transformer.setDestination(serializer);
        transformer.transform();

        // 获取最终的CSV字符串结果
        String result = writer.toString();
        System.out.println(result);
    }
}

关键步骤拆解:

  • 编译XSLT后创建XsltTransformer实例,负责执行转换逻辑
  • 用StringWriter作为输出目标,直接将转换结果转为字符串
  • 关联转换器与序列化器后调用transform(),完成整个转换流程

转换结果验证

运行代码后,得到的result字符串为:

test,Joe,34,test,12
test,Sam,24,main,45

完全符合预期的CSV格式,每个employee对应一行,逗号分隔字段,换行符分隔行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:01:30