How to read XML with LINQ, or what to do when the .NET XML classes don’t do what you expect and return null

C#
NameTable nameTable = new NameTable();
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("atom", "http://www.w3.org/2005/Atom");
string c = @"F:\Mona\Visual Studio 2008\Projects\LinqLearn\LinqLearn\sunamoblog.wordpress.2012-03-12.xml";
XmlDocument xmlDocument = new XmlDocument(nameTable);
xmlDocument.Load(c);
xmlDocument.Save(c);

You don’t have to worry about these namespaces getting duplicated, the XmlDocument class takes care of that.
Now to LINQ itself. Using the XDocument.Element method, I managed to get an element without a prefix, but whenever I gave it any prefix at all (for example {wp}), it also always returned null. However, this did not happen when I went through the found elements in a loop:

C#
i = 0;
foreach (XElement item in childNodes)
{
    Debug.Print(i.ToString() + " " + item.Name.LocalName);
    i++;
    if (item.Name.LocalName == "title")
    {
        title = item.Value;
    }
    else if (item.Name.LocalName == "extendedProperty" && item.Name.NamespaceName == "gd")
    {
        extendedProperty = item.Attribute("value").Value;
    }
}

As you can see, here you can specify both the LocalName and the Namespace to tell elements apart. And finally, one example of how to parse XML with a nested structure:

C#
private static void EnumeratingDescedantsFromElement()
{
    int i = 0;
    XDocument xDocument = XDocument.Load(@"F:\Mona\Visual Studio 2008\Projects\LinqLearn\LinqLearn\XMLFile1.xml");
    //-Always use the Elements method without a name
    IEnumerable<XElement> entries = xDocument.Root.Elements();
    foreach (XElement item in entries)
    {
        //-Only inside the loop can we check the node names and work with them accordingly
        //-We have to ask for LocalName, otherwise the program evaluates the condition as false
        if (item.Name.LocalName == "entry")
        {
            IEnumerable<XElement> childElements = item.Elements();
            foreach (XElement item2 in childElements)
            {
                Debug.Print(i.ToString() + " " + item2.Name.LocalName);
                i++;
            }
        }
    }
}

Otherwise it didn’t work for me, and honestly that’s no great loss. You work with it a little differently, but the main thing is that it works. Now I just hope it works every time and not just sometimes! 🙂

Categories

Leave a Reply