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

C#多层级航次XML文件读取及SQL入库技术问题求助

处理多层级XML数据并写入SQL数据库的解决方案

兄弟,我太懂你现在的头疼了——这种结构不固定的多层XML,用硬编码的switch-case去套,不仅容易漏节点,遇到新的嵌套层级直接就歇菜了。而且你还要处理数百条BL记录,效率和可维护性都是大问题。咱们一步步把这个问题拆解,既能解决你的当前困境,也能做出一个其他开发者能复用的通用XML转数据库工具。

第一步:用递归替代硬编码,搞定任意层级的XML解析

首先要放弃对节点名称的硬判断,改用递归遍历所有节点。这样不管XML嵌套多少层(比如BL下的Goods,Goods下的Dangerous Goods),都能完整抓取到数据。我们可以把每个节点的完整路径(比如BLs/BL1/Goods/Name)、节点名和值存起来,或者直接映射到对应的实体类里。

给你写个递归遍历的示例方法:

// 递归遍历所有XML节点,存储节点路径和值
private void TraverseXmlNodes(XElement node, string parentPath, Dictionary<string, string> dataDict)
{
    // 当前节点的完整路径
    string currentPath = string.IsNullOrEmpty(parentPath) ? node.Name.LocalName : $"{parentPath}/{node.Name.LocalName}";

    // 如果当前节点是叶子节点(没有子节点),就存入字典
    if (!node.HasElements)
    {
        dataDict[currentPath] = node.Value.Trim();
        return;
    }

    // 如果有子节点,继续递归遍历
    foreach (var childNode in node.Elements())
    {
        TraverseXmlNodes(childNode, currentPath, dataDict);
    }
}

然后你可以把原来的循环替换成这个递归方法,比如处理BLs的时候:

case "BLs":
    Globals.BLRecords.Clear(); // 假设BLRecords是存储每条BL数据的列表
    foreach (var blNode in x.Elements())
    {
        var blData = new Dictionary<string, string>();
        // 遍历当前BL下的所有节点,路径从BL的编号开始,方便区分不同BL
        TraverseXmlNodes(blNode, $"BL/{blNode.Element("number")?.Value}", blData);
        Globals.BLRecords.Add(blData);
    }
    break;

这样不管每条BL下面嵌套多少层的Goods、Dangerous Goods,都会被完整抓取到,路径里还包含了BL编号,不会混在一起。

第二步:把解析后的数据映射到DataView/DataTable

因为要写入SQL数据库,用DataTable作为中间层是最方便的。这里分两种场景:

  • 场景1:扁平化存储(适合快速原型或者简单结构):把所有节点的路径和值拼成一个大的DataTable,每条BL对应一行,列就是各个节点的路径(比如BL/123/Goods/Name)。
  • 场景2:按数据库范式拆分(推荐用于生产环境):把数据拆成多个关联的DataTable,比如Company、Voyage、BL、BL_Goods,每个表用主键关联(比如BL表的BLNumber作为BL_Goods表的外键)。

举个拆分的示例:

// 创建BL表的DataTable
DataTable blTable = new DataTable("BL");
blTable.Columns.Add("BLNumber", typeof(string));
blTable.Columns.Add("Shipper", typeof(string));
// 其他BL字段...

// 创建BL_Goods表的DataTable
DataTable blGoodsTable = new DataTable("BL_Goods");
blGoodsTable.Columns.Add("BLNumber", typeof(string));
blGoodsTable.Columns.Add("GoodsName", typeof(string));
blGoodsTable.Columns.Add("Weight", typeof(decimal));
// 其他货物字段...

// 遍历解析后的BL数据,填充DataTable
foreach (var blData in Globals.BLRecords)
{
    // 填充BL表
    DataRow blRow = blTable.NewRow();
    blRow["BLNumber"] = blData.First(kv => kv.Key.EndsWith("/number")).Value;
    blRow["Shipper"] = blData.TryGetValue("BL/Shipper", out var shipper) ? shipper : "";
    blTable.Rows.Add(blRow);

    // 填充BL_Goods表(假设一个BL对应多个Goods)
    var goodsNodes = blData.Where(kv => kv.Key.StartsWith("BL/Goods/")).GroupBy(kv => 
        kv.Key.Split('/')[2] // 按Goods的编号分组
    );
    foreach (var goodsGroup in goodsNodes)
    {
        DataRow goodsRow = blGoodsTable.NewRow();
        goodsRow["BLNumber"] = blData.First(kv => kv.Key.EndsWith("/number")).Value;
        goodsRow["GoodsName"] = goodsGroup.First(kv => kv.Key.EndsWith("/Name")).Value;
        goodsRow["Weight"] = decimal.Parse(goodsGroup.First(kv => kv.Key.EndsWith("/Weight")).Value);
        blGoodsTable.Rows.Add(goodsRow);
    }
}

// 把DataTable转成DataView(如果需要的话)
DataView blView = new DataView(blTable);

第三步:高效写入SQL数据库

如果是数百条BL记录,别用循环生成INSERT语句了,效率太低。用SqlBulkCopy直接把DataTable批量写入数据库,速度快N倍:

using (SqlConnection conn = new SqlConnection("你的数据库连接字符串"))
{
    conn.Open();
    // 批量写入BL表
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn))
    {
        bulkCopy.DestinationTableName = "dbo.BL";
        bulkCopy.WriteToServer(blTable);
    }
    // 批量写入BL_Goods表
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn))
    {
        bulkCopy.DestinationTableName = "dbo.BL_Goods";
        bulkCopy.WriteToServer(blGoodsTable);
    }
}

给其他开发者的复用思路

如果要做一个通用的XML读取器写入自有数据库,可以按这个流程来:

  1. 定义配置文件:让用户配置XML节点到数据库表字段的映射关系(比如哪个XML节点对应哪个表的哪个字段),不用改代码就能适配不同的XML结构。
  2. 动态生成DataTable:根据配置文件自动创建对应的DataTable,不用硬编码表结构。
  3. 递归解析+映射:用递归遍历XML,再根据配置把节点值映射到DataTable的对应列。
  4. 批量写入:统一用SqlBulkCopy提升性能。

这样不管遇到什么样的XML结构,只要改配置文件就能适配,灵活性拉满。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:44:09