Подтвердить что ты не робот

Лучший способ запроса XDocument с LINQ?

У меня есть документ XML, содержащий ряд узлов узлов, которые выглядят следующим образом:

<data>
    <item>
        <label>XYZ</label>
        <description>lorem ipsum</description>
        <parameter type="id">123</parameter>
        <parameter type="name">Adam Savage</parameter>
        <parameter type="zip">90210</parameter>
    </item> 
</data>

и я хочу LINQ в анонимный тип:

var mydata =
    (from root in document.Root.Elements("item")
    select new {
       label = (string)root.Element("label"),
       description = (string)root.Element("description"),
       id = ...,
       name = ...,
       zip = ...
     });

Какой лучший способ вывести каждый тип параметра в соответствии со значением его атрибута type? Поскольку есть много элементов параметров, вы заканчиваете с root.Elements("parameter"), который является коллекцией. Лучший способ, которым я могу это сделать, - это сделать это методом ниже, но я чувствую, что должен быть лучший способ?

(from c in root.Descendants("parameter") where (string)c.Attribute("type") == "id"
select c.Value).SingleOrDefault()
4b9b3361

Ответ 1

Я бы использовал встроенные методы запросов в LINQ to XML вместо XPath. Ваш запрос выглядит хорошо для меня, за исключением того, что:

  • Если есть несколько элементов, вам нужно будет найти потомков этого; или просто используйте Element, если вы ищете прямых потомков элемента
  • Возможно, вам захочется вытащить все значения сразу и преобразовать их в словарь
  • Если вы используете разные типы данных для содержимого, вы можете использовать этот элемент вместо .Value
  • Возможно, вам захочется создать метод для возврата соответствующего XElement для заданного типа вместо нескольких запросов.

Лично я не думаю, что даже использовал выражение запроса для этого. Например:

static XElement FindParameter(XElement element, string type)
{
    return element.Elements("parameter")
                  .SingleOrDefault(p => (string) p.Attribute("type") == type);
}

Тогда:

var mydata = from item in document.Root.Elements("item")
             select new {
                 Label = (string) item.Element("label"),
                 Description = (string) item.Element("description"),
                 Id = (int) FindParameter(item, "id"),
                 Name = (string) FindParameter(item, "name"),
                 Zip = (string) FindParameter(item, "zip")
             };

Я подозреваю, что вы найдете эту опрятную, чем любая альтернатива, используя XPath, предполагая, что я понял, что вы пытаетесь сделать.

Ответ 2

использовать XPATH - это очень быстро (кроме xmlreader - но лот of if)

   using (var stream = new StringReader(xml))
   {
    XDocument xmlFile = XDocument.Load(stream);

    var query = (IEnumerable)xmlFile.XPathEvaluate("/data/item/parameter[@type='id']");

     foreach (var x in query.Cast<XElement>())
     {
         Console.WriteLine(  x.Value );
     }

    }