XMLTextReader not reading an element content

2019-03-29 06:28发布

问题:

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?

回答1:

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;
                }
            }
        }
    }
    
    }