Query elemento opzionale LINQ to XML
-
07-07-2019 - |
Domanda
Sto lavorando con un documento XML esistente che ha una struttura (in parte) in questo modo:
<Group>
<Entry>
<Name> Bob </Name>
<ID> 1 </ID>
</Entry>
<Entry>
<Name> Larry </Name>
</Entry>
</Group>
Sto usando LINQ to XML per interrogare XDocument per recuperare tutte queste voci come segue:
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"
};
L'ID " " gli elementi non sono sempre presenti e quindi la mia soluzione è stata il Count () jazz sopra. Ma mi chiedo se qualcuno ha un modo migliore per farlo. Mi sto ancora sentendo a mio agio con queste nuove cose e sospetto che potrebbe esserci un modo migliore per farlo rispetto a come lo sto attualmente facendo.
Esiste un modo migliore / più preferito per fare ciò che voglio?
Soluzione
XElement attualmente ha operatori di conversione esplicita interessanti che fanno la cosa giusta in questo caso.
Quindi raramente è necessario accedere alla proprietà .Value
.
Questo è tutto ciò che serve per la tua proiezione:
var items =
from g in xDocument.Root.Descendants("Group").Elements("Entry")
select new
{
name = (string) g.Element("Name"),
id = (string) g.Element("ID") ?? "none",
};
E se preferisci utilizzare il valore di ID
come numero intero nel tuo tipo anonimo:
var items =
from g in xDocument.Root.Descendants("Group").Elements("Entry")
select new
{
name = (string) g.Element("Name"),
id = (int?) g.Element("ID"),
};
Altri suggerimenti
In una situazione simile ho usato un metodo di estensione:
public static string OptionalElement(this XElement actionElement, string elementName)
{
var element = actionElement.Element(elementName);
return (element != null) ? element.Value : null;
}
utilizzo:
id = g.OptionalElement("ID") ?? "none"
Che ne dici di:
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;
};
se questo barfs, allora FirstOrDefault ()
ecc potrebbe essere utile, altrimenti basta usare un metodo di estensione (come già suggerito).