使用 XDocument 使用重复键从 XML 中读取

Reading from XML with repeated keys using XDocument

我需要 XDocument 方面的帮助。我有文件:

<?xml version="1.0" encoding="utf-8" ?>
<SaleGroupsFiles>
  <SaleGroup id="1" active="true" name="US"> 
   <files
      location="c:\mypath\"
      fileType="pdf"
      destination="outputpath">
    </files>
  </SaleGroup>

  <SaleGroup id="2" active="true" name="Canada"> 
   <files
      location="c:\mypath\"
      fileType="pdf"
      destination="outputpath">
    </files>
  </SaleGroup>
</SaleGroups>

我正在尝试使用 XDocument 读取文件

static Dictionary<string, string> GetSettings(string path)
    {
        var document = XDocument.Load(path);
        var root = document.Root;
        var results =
          root
            .Elements()
            .ToDictionary(element => element.Name.ToString(), element => element.Value);
        return results;

    }

出现错误 "element with that key already exists in dictionary"。我猜这是因为 "SaleGroup" 重复了不止一次。

读取数据的正确方法是什么?

你的推测是正确的;正如@maccettura 所解释的,这就是 Dictionary 的工作原理。

这就是说,请记住 <SaleGroupsFiles> 应该有一个匹配的标签以使您的 XML 有效。

根据你的问题,这是一个可能的想法:

var results =
    root
        .Descendants("SaleGroup")
        .ToDictionary(element => element.Attribute("id").Value.ToString(), element => element.ToString());

即添加元素的 id 属性的值作为键,假设它们是唯一的。

其实这个问题

What is the proper way to read the data?

很难回答,因为...这取决于您要对数据执行的操作。 您要创建 SaleGroup 个对象吗?在这种情况下,如果您提供 SaleGroup class.

,则无需创建字典,只需创建 List<SaleGroup>

另一种选择是 deserializing 你的 XML。

此外,请记住 element.Name 将给出元素的名称(例如 SaleGroup),而您可能想要读取 name 属性的值(例如 "Canada") ?


编辑

既然你可以接受稍微现实一点的解决方案,如果你声明这些 classes

public class SaleGroup
{
    public int Id { get; set; }
    public bool Active { get; set; }
    public string Name { get; set; }
    public SaleFile File { get; set; }
}

public class SaleFile
{
    public string Location { get; set; }
    public string FileType { get; set; }
    public string Destination { get; set; }
}

您可以这样编辑代码:

var results =
          root
            .Descendants("SaleGroup")
            .Select(element => new SaleGroup()
            {
                Active = Convert.ToBoolean(element.Attribute("active").Value),
                Id = Convert.ToInt32(element.Attribute("id").Value),
                Name = element.Attribute("name").Value,
                File = new SaleFile()
                {
                    Destination = element.Descendants("files").Single().Attribute("destination").Value,
                    FileType = element.Descendants("files").Single().Attribute("fileType").Value,
                    Location = element.Descendants("files").Single().Attribute("location").Value
                }
            })
            .ToList();

也可以优化上面的代码,例如只阅读 element.Descendants("files").Single() 一次,或修改它以在 SaleGroup class.

中允许多个 SaleFile