Попытка проанализировать XML-дерево с помощью Linq to XML (C#)

Я хотел бы отразить XML-дерево в своей структуре объектов, но я совсем новичок в LINQ to XML.

У меня есть XML со следующей структурой:

<questions>
<question id="q1">
  <number>1</number>
  <text>some text11</text>
  <answers>
     <answer>
      <v>some text11</v>
    </answer>
    <answer>
      <v>some text11</v>
    </answer>
  </answers>
</question>
<question id="q2">
  <number>2</number>
  <text>some text2</text>

<answers>
    <answer>
      <v>some text22</v>
    </answer>
    <answer>
      <v>some text22</v>
    </answer>
  </answers>
</question>
<question id="q3">
  <number>3</number>
  <text>some text3</text>
  <answers>
    <answer>
      <v>some text33</v>
    </answer>
    <answer>
      <v>some text33</v>
    </answer>
    <answer>
      <v>some text33</v>
      <addDescription>some text333</addDescription>
      <textBox/>
    </answer>
  </answers>
</question>
</questions>

... и у меня есть следующие классы:

public class Question
{
    public string text { get; set; }
    public IList<Anwser> anwsers = new List<Anwser>();
}

public class Anwser
{
    public string content { get; set; }
}

... и я построил следующий (неправильный) запрос Linq:

        List<Question> questions = (from xml in xdoc.Element("survey").Elements("questions").Elements("question")
                                    select new Question()
                                               {
                                                   text = xml.Element("text").Value,
                                                   anwsers =
                                                       (from anwsers in
                                                            xdoc.Element("survey").Elements("questions").Elements("question").Elements(
                                                            "answers").Elements(
                                                            "answer")
                                                        select new Anwser()
                                                                   {
                                                                       content = anwsers.Element("v").Value
                                                                   }

                                                       ).ToList()
                                            }).ToList();

Конечно, таким образом я каждый раз получаю все ответы на все вопросы, добавленные в каждый список. Как это решить? Я могу представить, что это просто, но я понятия не имею :)

Заранее спасибо!


person Kamil Zadora    schedule 26.04.2009    source источник


Ответы (3)


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

List<Question> questions = (from question in xdoc.Element("survey").Element("questions").Elements("question")
         select new Question
         {
           text = question.Element("text").Value,
           anwsers = (from answer in question.Element("answers").Elements("answer")
                select new Anwser
                {
                  content = answer.Element("v").Value
                }).ToList()
         }).ToList();
person Samuel    schedule 26.04.2009
comment
Имеет ли использование LINQ для анализа XML какое-либо преимущество перед использованием XmlDocument? - person B Faley; 27.01.2012

Вы были очень близки. В выбранных новых частях вам не нужны () после имен классов. Также вы хотите использовать .Descdents() вместо .Elements(). Единственная другая часть заключалась в том, что ответы должны использовать xml var, не возвращаясь к исходному документу, это дает вам ответы, связанные с вопросом.

List<Question> questions = (from xml in xdoc.Descendants("question")
                                    select new Question
                                    {
                                        text = xml.Element("text").Value,
                                        answers =
                                            (from anwsers in xml.Descendants("answer")
                                             select new Answer
                                             {
                                                 Content = anwsers.Element("v").Value
                                             }

                                            ).ToList()
                                    }).ToList();
person Alexander Kahoun    schedule 26.04.2009
comment
Что вы имеете в виду под своим последним заявлением? Создание новой ссылки на тот же SelectIterator не приведет к выполнению запроса. - person Samuel; 27.04.2009
comment
Сэмюэль, чтобы правильно назначить его, строка будет выглядеть примерно так: Список‹Вопросы› мои Вопросы = вопросы.ToList() Только вызов .ToList() или использование запроса в foreach будет выполняться. - person Alexander Kahoun; 27.04.2009
comment
Тогда вам следует отказаться от этого утверждения. Поскольку он предлагает вам выполнить его, вам нужно выполнить List‹Question› temp = (...).ToList(); а затем Список‹Вопрос› вопросов = temp;. - person Samuel; 27.04.2009
comment
Хороший улов, спасибо, Самуэль. Я так привык использовать var и получать значение позже, что совершенно забыл, что .ToList() уже был в операторе. - person Alexander Kahoun; 27.04.2009

Проблема заключается в том, что вы начинаете с xdoc во внутреннем выборе, если вы должны были изменить его на:

from answer in xml.Elements("answers").Elements("answer")

Вы должны быть в порядке. Это должно работать, потому что xml содержит элемент вопроса.

person Duncan    schedule 26.04.2009