web-dev-qa-db-fra.com

Vérifier si un élément existe lors de l'analyse XML

Je suis en train d'analyser XML. Je l’analyse normalement comme je le montre dans le code ci-dessous, ce qui est simple Le problème est que je ne possède pas le code XML que j’analyse et que je ne peux pas le modifier. Parfois, il n'y a pas d'élément miniature (il n'y a pas de balises) et j'obtiens un Exception.

Existe-t-il un moyen de maintenir cette simplicité et de vérifier si l'élément existe? Ou dois-je d'abord obtenir une liste XElement avec LINQ, puis la vérifier et ne renseigner que les propriétés d'objet existantes?

void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    XDocument dataDoc = XDocument.Load(new StringReader(e.Result));

    var listitems = from noticia in dataDoc.Descendants("Noticia")
                    select new News()
                    {
                        id = noticia.Element("IdNoticia").Value,
                        published = noticia.Element("Data").Value,
                        title = noticia.Element("Titol").Value,
                        subtitle = noticia.Element("Subtitol").Value,
                        thumbnail = noticia.Element("Thumbnail").Value
                    };

    itemList.ItemsSource = listitems;
}
30
enkara

[Edit]La réponse de Jon Skeet devrait être la réponse acceptée. Il est beaucoup plus lisible et plus facile à appliquer .[/ edit]

Créez une méthode d'extension comme ceci:

public static string TryGetElementValue(this XElement parentEl, string elementName, string defaultValue = null) 
{
    var foundEl = parentEl.Element(elementName);

    if (foundEl != null)
    {
        return foundEl.Value;
    }

    return defaultValue;
}

alors, changez votre code comme ceci:

select new News()
{
    id = noticia.TryGetElementValue("IdNoticia"),
    published = noticia.TryGetElementValue("Data"),
    title = noticia.TryGetElementValue("Titol"),
    subtitle = noticia.TryGetElementValue("Subtitol"),
    thumbnail = noticia.TryGetElementValue("Thumbnail", "http://server/images/empty.png")
};

Cette approche vous permet de garder un code propre en isolant la vérification de la présence d'éléments. Cela vous permet également de définir une valeur par défaut, ce qui peut être utile

43
Steve B

Au lieu d'utiliser la propriété Value, si vous transformez en chaîne, vous obtiendrez simplement une référence null:

void wc_DownloadStringCompleted(object sender,
                                DownloadStringCompletedEventArgs e)
{
    XDocument dataDoc = XDocument.Load(new StringReader(e.Result));

    var listitems = from noticia in dataDoc.Descendants("Noticia")
                    select new News()
                    {
                        id = (string) noticia.Element("IdNoticia"),
                        published = (string) noticia.Element("Data"),
                        title = (string) noticia.Element("Titol"),
                        subtitle = (string) noticia.Element("Subtitol"),
                        thumbnail = (string) noticia.Element("Thumbnail")
                    };

    itemList.ItemsSource = listitems;
}

Cela utilise la conversion explicite de XElement à string, qui gère une entrée NULL en renvoyant une sortie NULL. Il en va de même pour toutes les conversions explicites sur XAttribute et XElement en types nullable, y compris les types de valeur nullable tels que int? - vous devez simplement faire attention si vous utilisez nested elements. Par exemple:

string text = (string) foo.Element("outer").Element("inner");

donnera une référence nulle si inner est manquant, mais lève toujours une exception si outer est manquant.

Si vous voulez une valeur "par défaut", vous pouvez utiliser l'opérateur de coalescence nul (??):

string text = (string) foo.Element("Text") ?? "Default value";
34
Jon Skeet

Vous pouvez simplement utiliser le System.Xml.Serialization.XmlSerializer pour le désérialiser du XML à un objet. Ensuite, si l'élément n'existe pas, la propriété de l'objet obtiendra simplement sa valeur par défaut.

Regardez ici: http://msdn.Microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx Ou le nouveau chemin https : //docs.Microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer

0
Bazzz