Запрос необязательного элемента LINQ to XML
Я работаю с существующим документом XML, который имеет структуру (частично) следующим образом:
<Group>
<Entry>
<Name> Bob </Name>
<ID> 1 </ID>
</Entry>
<Entry>
<Name> Larry </Name>
</Entry>
</Group>
Я использую LINQ to XML для запроса XDocument для извлечения всех этих записей следующим образом:
var items = from g in xDocument.Root.Descendants("Group").Elements("Entry")
select new
{
name = (string)g.element("Name").Value,
id = g.Elements("ID").Count() > 0 ? (string)g.Element("ID").Value : "none"
};
Элементы "ID" не всегда существуют, и поэтому я решил, что это был джаз Count(). Но мне интересно, есть ли у кого-то лучший способ сделать это. Мне все еще нравится этот новый материал, и я подозреваю, что может быть лучший способ сделать это, чем то, как я это делаю сейчас.
Есть ли лучший/более предпочтительный способ сделать то, что я хочу?
Ответы
Ответ 1
XElement фактически имеет интересные явные операторы преобразования которые делают в этом случае правильные вещи.
Итак, вам редко приходится обращаться к свойству .Value
.
Это все, что вам нужно для вашей проекции:
var items =
from g in xDocument.Root.Descendants("Group").Elements("Entry")
select new
{
name = (string) g.Element("Name"),
id = (string) g.Element("ID") ?? "none",
};
И если вы предпочитаете использовать значение ID
как целое число в вашем анонимном типе:
var items =
from g in xDocument.Root.Descendants("Group").Elements("Entry")
select new
{
name = (string) g.Element("Name"),
id = (int?) g.Element("ID"),
};
Ответ 2
В аналогичной ситуации я использовал метод расширения:
public static string OptionalElement(this XElement actionElement, string elementName)
{
var element = actionElement.Element(elementName);
return (element != null) ? element.Value : null;
}
использование:
id = g.OptionalElement("ID") ?? "none"
Ответ 3
Как насчет:
var items = from g in xDocument.Root.Descendants("Group").Elements("Entry")
let idEl = g.Element("ID")
select new
{
name = (string)g.element("Name").Value,
id = idEl == null ? "none" : idEl.Value;
};
если это barfs, тогда FirstOrDefault()
и т.д. может быть полезно, иначе просто используйте метод расширения (как уже было предложено).