SSIS中遍历XML文件需用Foreach File Enumerator,路径用变量动态拼接;结构简单用XML Source,复杂用Script Task解析为DataTable;小数据量用ADO NET Destination并调优BatchSize,大数据量用SqlBulkCopy;异常须在Script Task内捕获,且需检查文件锁。

SSIS中用For Each Loop遍历XML文件的正确配置
SSIS本身不直接解析XML结构,但能可靠地按文件名批量获取XML文件。关键在For Each Loop Container里选对枚举器类型:必须用Foreach File Enumerator,而非Foreach ADO Enumerator或Foreach Item Enumerator。
常见错误是路径写成硬编码(如C:\Data\*.xml),导致部署到其他服务器失败。应使用SSIS变量+表达式动态拼接:
-
Directory属性设为变量@[User::SourceFolder],该变量值通过配置文件或环境变量注入 -
Files填*.xml,勾选Retrieve file name→Full qualified - 在循环体内,用
FileSpec变量(如@[User::CurrentXMLPath])传递完整路径给后续任务
XML文件内容读取:Script Task还是XML Source?
如果XML结构固定且简单(如扁平化单层记录),可用XML Source组件配合XSD架构文件;但多数业务XML含嵌套、命名空间或可选字段,这时Script Task更可控。
推荐用C#脚本(.NET Framework 4.7.2+)读取并转为DataTable,避免XML Source因格式微小差异直接报错:
public void Main()
{
string xmlPath = Dts.Variables["User::CurrentXMLPath"].Value.ToString();
XmlDocument doc = new XmlDocument();
doc.Load(xmlPath);
// 示例:提取所有节点下的子元素
var orders = doc.SelectNodes("//Order");
DataTable dt = new DataTable();
dt.Columns.Add("OrderId", typeof(string));
dt.Columns.Add("Amount", typeof(decimal));
foreach (XmlNode node in orders)
{
DataRow row = dt.NewRow();
row["OrderId"] = node.SelectSingleNode("OrderId")?.InnerText;
row["Amount"] = decimal.TryParse(node.SelectSingleNode("Amount")?.InnerText, out decimal a) ? a : 0;
dt.Rows.Add(row);
}
Dts.Variables["User::ParsedOrders"].Value = dt;
Dts.TaskResult = (int)ScriptResults.Success;
}
注意:Script Task需在ReadOnlyVariables里声明User::CurrentXMLPath,在ReadWriteVariables里声明User::ParsedOrders。
上传到SQL Server:用ADO NET Destination还是Execute SQL Task?
当解析后数据量不大(单文件<1万行),用ADO NET Destination直连目标表最简;若需事务控制、UPSERT逻辑或目标表有触发器,改用Execute SQL Task配合临时表更稳妥。
性能差异明显:ADO NET Destination默认无批处理,插入10万行可能比BULK INSERT慢3倍以上。此时应:
- 在
ADO NET Connection Manager的连接字符串末尾加;Packet Size=8192; - 把
BatchSize属性设为5000(不是默认的0) - 若用
Execute SQL Task,先用SqlBulkCopy写入临时表,再MERGE到主表
错误处理与日志:别只靠Event Handler
SSIS默认Event Handler捕获不到XML解析异常(比如编码错误、非法字符),必须在Script Task内手动捕获并写入日志变量:
try
{
doc.Load(xmlPath);
}
catch (XmlException ex)
{
Dts.Events.FireError(0, "XML Parse Error",
$"Failed to load {xmlPath}: {ex.Message}", "", 0);
Dts.Variables["User::LastError"].Value = ex.Message;
Dts.TaskResult = (int)ScriptResults.Failure;
return;
}
真正容易被忽略的是文件锁问题:某些系统生成XML时会短暂独占写入,SSIS直接读取会抛System.IO.IOException: The process cannot access the file。解决方案不是重试,而是加前置判断——用Script Task检查文件是否可读(尝试OpenRead后立即Close),不可读则跳过或延时重试。










