-->

problem parsing with XMLReader (using ReadSubTree)

2019-06-05 19:33发布

问题:

Im trying to build a simple XML to Controls parser in my CF application. In the code below the string im trying to parse looks like this:

"<Panel><Label>Text1</Label><Label>Text2</Label></Panel>"

The result i want with this code would be a Panel with two labels. But the problem is when the first Label is parsed the subreader.Read() returns false in the ParsePanelElementh method, and so it falls out of while statement. Since im new into XMLReader i must be missing something very simple. Any help would be apreciated !

peace.

static class XMLParser
{
    public static Control Parse(string aXmlString)
    {
        XmlReader reader = XmlReader.Create(new StringReader(aXmlString));
        return ParseXML(reader);
    }

    public static Control ParseXML(XmlReader reader)
    {
        using (reader)
        {
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    if (reader.LocalName == "Panel")
                    {
                        return ParsePanelElement(reader);
                    }

                    if (reader.LocalName == "Label")
                    {
                        return ParseLabelElement(reader);
                    }
                }
            }
        }
        return null;
    }

    private static Control ParsePanelElement(XmlReader reader)
    {
        var myPanel = new Panel();
        XmlReader subReader = reader.ReadSubtree();
        while (subReader.Read())
        {
            Control subControl = ParseXML(subReader);
            if (subControl != null)
            {
                myPanel.Controls.Add(subControl);
            };
        }
        return myPanel;
    }

    private static Control ParseLabelElement(XmlReader reader)
    {
        reader.Read();
        var myString = reader.Value as string;
        var myLabel = new Label();
        myLabel.Text = myString;
        return myLabel;
    }
}

回答1:

The problem is that the reader reads twice, once in ParsePanelElement and once in ParseXML. This way you parse the panel, skip the first label and eventually add the second label.

[EDIT May 3rd 2010]

This code works under Visual Studio 9. (I have moved the using clause)

   static class Program
   {
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         Control Test = XMLParser.Parse("<Panel><Label>Text1</Label><Label>Text2</Label></Panel>");
         for (Int32 i = 0; i < Test.Controls.Count; i++)
         {
            System.Diagnostics.Debug.WriteLine("Control " + i + ": " + Test.Controls[i].GetType().FullName + " [TEXT = " + Test.Controls[i].Text + "]");
         }
      }

      static class XMLParser
      {
         public static Control Parse(string aXmlString)
         {
            Control result = null;
            using (StringReader strReader = new StringReader(aXmlString))
            {
               using (XmlReader reader = XmlReader.Create(strReader))
               {
                  result = ParseXML(reader);
               }
            }
            return result;
         }

         public static Control ParseXML(XmlReader reader)
         {
            while (reader.Read())
            {
               if (reader.NodeType == XmlNodeType.Element)
               {
                  if (reader.LocalName == "Panel")
                  {
                     return ParsePanelElement(reader);
                  }

                  if (reader.LocalName == "Label")
                  {
                     return ParseLabelElement(reader);
                  }
               }
            }
            return null;
         }

         private static Control ParsePanelElement(XmlReader reader)
         {
            var myPanel = new Panel();
            using (XmlReader subReader = reader.ReadSubtree())
            {
               while (subReader.Read())
               {
                  Control subControl = ParseXML(subReader);
                  if (subControl != null)
                  {
                     myPanel.Controls.Add(subControl);
                  };
               }
            }
            return myPanel;
         }

         private static Control ParseLabelElement(XmlReader reader)
         {
            reader.Read();
            var myString = reader.Value as string;
            var myLabel = new Label();
            myLabel.Text = myString;
            return myLabel;
         }
      }
   }