XMLTextReader not reading an element content

Learner picture Learner · Oct 13, 2010 · Viewed 21k times · Source
static void ReadXml()
{
    string a= null;
    double b= 0;
    double c= 0;
    XmlReader xmlReader = new XmlReader("Testxml.xml");
    xmlReader.
    using (xmlReader)
    {
        if (xmlReader != null)
        { 
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType == XmlNodeType.Element)
                {
                    switch (xmlReader.Name)
                    {
                        case "a":
                            a = xmlReader.ReadElementContentAsString();

                            break;
                        case "b":
                            b = double.Parse(xmlReader.ReadElementContentAsString());

                            break;
                        case "c":
                            c = double.Parse(xmlReader.ReadElementContentAsString());

                            break;
                    }
                }
            }
        }
    }
}

TestXML content:

<a><b>26a83f12c782</b><c>128</c><d>12</d></a>

Case b is never hit. But If I add a space after end element of b, case b is hit. Now how to make it work without changing the xml file?

Answer

Samuel Neff picture Samuel Neff · Oct 13, 2010

Here's a working version of your code. The specific problems that are corrected include:

  1. new XmlReader doesn't compile. It's an abstract class. You need to use XmlTextReader or another XmlReader derived class.

  2. b is not a valid double. You were trying to convert a large hex number to a double directly which isn't possible. You can use NumberStyles.HexNumber in the Parse call, but not with double, it has to be long or int.

  3. Double read. You were calling Read() inside a loop but then using the XmlReader.ReadXxx() methods as well. This was calling read extra times and skipping nodes. This is really the main problem you were asking about. The following code keeps track of the last element found and then waits till it hits the Text node for processing. This is fine for simple/flat documents, but for more complex ones you need a better way of keeping track of state, like a finite state machine. Or use DOM. Or LINQ.

    static void ReadXml()
    {
        string a = null;
        long b = 0;
        double c = 0;
        string text = "<a><b>26a83f12c782</b><c>128</c><d>12</d></a>";
        string element = "";
    
    
    
    using (XmlReader xmlReader = new XmlTextReader(new StringReader(text)))
    {
        while (xmlReader.Read())
        {
            if (xmlReader.NodeType == XmlNodeType.Element)
            {
                element = xmlReader.Name;
            }
            else if (xmlReader.NodeType == XmlNodeType.Text)
            {
                switch (element)
                {
                    case "a":
                        a = xmlReader.Value;
                        Console.WriteLine("a: " + a);
                        break;
                    case "b":
                        b = long.Parse(xmlReader.Value, NumberStyles.HexNumber);
                        Console.WriteLine("b: " + b);
                        break;
                    case "c":
                        c = double.Parse(xmlReader.Value);
                        Console.WriteLine("c: " + c);
                        break;
                }
            }
        }
    }
    
    }