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

在SSIS脚本任务中用Open XML SDK实现XML转CSV的问题求助

刚好我之前处理过类似的场景,给你一个完美的无Office依赖解决方案!因为服务器没装Office,依赖COM组件的Interop肯定跑不起来,而你提到的XML Spreadsheet 2003是基于纯XML的格式,我们直接用.NET自带的XML解析类就能搞定,完全不需要Open XML SDK(当然如果是处理.xlsx格式才需要SDK,你的场景用原生XML解析更高效)。

实现步骤和代码

1. 准备SSIS脚本任务环境

打开你的SSIS脚本任务编辑器,点击「编辑脚本」进入代码编辑界面,确保项目已经引用了System.Xml.Linq(默认应该包含,没有的话右键项目→添加引用即可)。

2. 完整转换代码

下面是直接可用的C#代码,包含了XML读取、数据提取和CSV写入的逻辑,还处理了CSV的特殊字符转义:

using System;
using System.IO;
using System.Xml.Linq;
using Microsoft.SqlServer.Dts.Runtime;

namespace ST_YourScriptNamespace // 替换成你自己的脚本任务命名空间
{
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
        public void Main()
        {
            bool fireAgain = true;
            try
            {
                // 可以替换成SSIS变量,比如从User::SourceXmlPath和User::TargetCsvPath获取
                string xmlSourcePath = @"C:\Input\YourSpreadsheet.xml";
                string csvTargetPath = @"C:\Output\Result.csv";

                // XML Spreadsheet 2003的核心命名空间,必须指定才能正确定位元素
                XNamespace ssNs = "urn:schemas-microsoft-com:office:spreadsheet";

                // 加载XML文档
                XDocument xmlDoc = XDocument.Load(xmlSourcePath);

                // 获取第一个工作表(如果有多个工作表,可循环处理所有Descendants(ssNs + "Worksheet"))
                var targetWorksheet = xmlDoc.Descendants(ssNs + "Worksheet").FirstOrDefault();
                if (targetWorksheet == null)
                {
                    Dts.Events.FireError(0, "解析失败", "XML文件中未找到工作表", string.Empty, 0);
                    Dts.TaskResult = (int)DTSExecResult.Failure;
                    return;
                }

                // 遍历所有行并写入CSV
                using (StreamWriter csvWriter = new StreamWriter(csvTargetPath))
                {
                    foreach (var row in targetWorksheet.Descendants(ssNs + "Row"))
                    {
                        var cells = row.Descendants(ssNs + "Cell");
                        string[] csvRowCells = new string[cells.Count()];
                        int cellIdx = 0;

                        foreach (var cell in cells)
                        {
                            // 提取单元格值:有些值在<ss:Data>子元素里,有些直接在Cell节点文本中
                            var dataElement = cell.Element(ssNs + "Data");
                            string cellValue = dataElement?.Value ?? cell.Value;
                            // 转义CSV特殊字符(逗号、引号、换行)
                            csvRowCells[cellIdx] = EscapeCsvContent(cellValue);
                            cellIdx++;
                        }

                        // 写入一行CSV
                        csvWriter.WriteLine(string.Join(",", csvRowCells));
                    }
                }

                Dts.Events.FireInformation(0, "转换完成", $"已成功将文件 {xmlSourcePath} 转换为CSV:{csvTargetPath}", string.Empty, 0, ref fireAgain);
                Dts.TaskResult = (int)DTSExecResult.Success;
            }
            catch (Exception ex)
            {
                Dts.Events.FireError(0, "转换异常", $"错误信息:{ex.Message}\n堆栈跟踪:{ex.StackTrace}", string.Empty, 0);
                Dts.TaskResult = (int)DTSExecResult.Failure;
            }
        }

        // 辅助方法:处理CSV内容的特殊字符转义
        private string EscapeCsvContent(string content)
        {
            if (string.IsNullOrEmpty(content))
                return string.Empty;

            // 如果内容包含逗号、引号或换行,需要用双引号包裹,内部的双引号替换为两个双引号
            if (content.Contains(",") || content.Contains("\"") || content.Contains("\n") || content.Contains("\r"))
            {
                return $"\"{content.Replace("\"", "\"\"")}\"";
            }

            return content;
        }
    }
}

3. 关键注意事项

  • 命名空间必须指定:XML Spreadsheet 2003的所有元素都属于urn:schemas-microsoft-com:office:spreadsheet命名空间,忽略这个会导致找不到任何节点。
  • SSIS变量集成:如果需要动态指定输入输出路径,把代码中的硬编码路径替换为Dts.Variables["User::YourVariableName"].Value.ToString(),记得在脚本任务的「ReadOnlyVariables」中添加对应的变量。
  • 多工作表处理:如果你的XML文件包含多个工作表,把FirstOrDefault()改成循环遍历所有Descendants(ssNs + "Worksheet")即可,还可以根据<ss:Name>元素的值筛选特定工作表。

关于Open XML SDK的补充

如果你其实是要处理.xlsx格式的文件(真正的Open XML格式),那才需要用到Open XML SDK,此时需要先在脚本项目中安装DocumentFormat.OpenXml NuGet包,然后通过SpreadsheetDocument类来解析工作簿。但针对你提到的XML Spreadsheet 2003(后缀为.xml的Excel格式),上面的原生XML解析方案是最轻便、无额外依赖的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:50:07