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

使用XDocument读取含重复节点的XML遇键重复错误,求正确读取方法

解决XDocument读取重复节点导致的字典键冲突问题

你猜的完全正确!这个错误就是因为XML里重复的SaleGroup节点引发的——ToDictionary方法要求所有键必须唯一,但你的两个节点名称都是SaleGroup,自然会触发“键已存在”的异常。而且还要注意,你原来代码里的element.Value其实是空字符串,因为SaleGroup节点的内容是子节点<files>,不是文本内容,这个值对你的需求来说没什么实际意义。

下面给你几种符合需求的正确读取方式:

方案1:用唯一属性作为字典键(推荐)

如果每个SaleGroup的name或id是唯一的,可以用它们作为字典的键,把对应的文件配置信息作为值。比如用name作为键:

static Dictionary<string, (string Location, string FileType, string Destination)> GetSaleGroupSettings(string path)
{
    var document = XDocument.Load(path);
    
    return document.Root
        .Elements("SaleGroup")
        .ToDictionary(
            // 用SaleGroup的name属性作为唯一键
            saleGroup => saleGroup.Attribute("name").Value,
            saleGroup => 
            {
                var filesNode = saleGroup.Element("files");
                // 返回files节点的属性信息
                return (
                    Location: filesNode.Attribute("location").Value,
                    FileType: filesNode.Attribute("fileType").Value,
                    Destination: filesNode.Attribute("destination").Value
                );
            });
}

如果担心XML里可能缺失属性,可以加上空值判断(避免NullReferenceException):

saleGroup => saleGroup.Attribute("name")?.Value ?? string.Empty,

方案2:返回SaleGroup配置列表

如果不需要字典,只是想读取所有SaleGroup的完整配置,最好返回一个实体类列表,这样更清晰也更灵活:

首先定义一个对应配置的实体类:

public class SaleGroupConfig
{
    public int Id { get; set; }
    public bool IsActive { get; set; }
    public string Name { get; set; }
    public string FilesLocation { get; set; }
    public string FileType { get; set; }
    public string DestinationPath { get; set; }
}

然后读取XML的代码:

static List<SaleGroupConfig> GetAllSaleGroupSettings(string path)
{
    var document = XDocument.Load(path);
    
    return document.Root
        .Elements("SaleGroup")
        .Select(sg => new SaleGroupConfig
        {
            Id = int.Parse(sg.Attribute("id").Value),
            IsActive = bool.Parse(sg.Attribute("active").Value),
            Name = sg.Attribute("name").Value,
            FilesLocation = sg.Element("files").Attribute("location").Value,
            FileType = sg.Element("files").Attribute("fileType").Value,
            DestinationPath = sg.Element("files").Attribute("destination").Value
        })
        .ToList();
}

方案3:按节点名称分组(如果需要保留重复键的场景)

如果确实需要按节点名称分组处理(比如后续要批量操作同类型节点),可以用GroupBy:

static IEnumerable<IGrouping<string, XElement>> GetGroupedSaleGroups(string path)
{
    var document = XDocument.Load(path);
    return document.Root.Elements().GroupBy(element => element.Name.ToString());
}

之后你可以遍历每个分组,处理里面的SaleGroup节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:45:47