Чтение из XML с повторяющимися ключами с использованием XDocument - PullRequest
0 голосов
/ 09 мая 2018

Мне нужна помощь с 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;

    }

получаю ошибку "элемент с таким ключом уже существует в словаре". Полагаю, это происходит потому, что «SaleGroup» повторяется более одного раза.

Как правильно читать данные?

1 Ответ

0 голосов
/ 09 мая 2018

Ваше предположение верно; как объяснил @maccettura, так работает Dictionary.

При этом помните, что <SaleGroupsFiles> должен иметь соответствующий тег, чтобы ваш XML был действительным.

По вашему вопросу это возможная идея:

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

т.е. добавив в качестве ключей значение атрибута id ваших элементов, предположив, что они уникальны.

Собственно этот вопрос

Как правильно читать данные?

трудно ответить, поскольку ... это зависит от того, что вы хотите сделать с данными. Вы хотите создать SaleGroup объекты? В этом случае вместо создания словаря вы можете просто создать List<SaleGroup>, если вы предоставите класс SaleGroup.

Другим вариантом будет десериализация вашего XML.

Кроме того, имейте в виду, что element.Name даст имя элемента (например, SaleGroup), в то время как, возможно, вы захотите прочитать значение атрибута name (например, "Canada")? *


EDIT

Поскольку у вас все в порядке с немного более реалистичным решением, если вы объявите эти классы

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 классе было более одного SaleFile.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...