在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
相关产品推荐
相关产品推荐

