2010-04-29 3 views
1

Я пытаюсь создать простой XML-элемент для управления парсером в моем приложении CF. В коде ниже строки им пытаются разобрать, выглядит так:Анализ проблемы с XMLReader (с использованием ReadSubTree)

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

В результате я хочу с этим кодом будет панель с двумя метками. Но проблема в том, когда первая метка анализируется подредактором. Read() возвращает false в методе ParsePanelElementh, и поэтому он выпадает из инструкции while. Поскольку я новый в XMLReader, я должен пропустить что-то очень простое. Любая помощь будет оценена!

мир.

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

ответ

3

Проблема заключается в том, что читатель читает дважды, один раз в ParsePanelElement и один раз в ParseXML. Таким образом, вы анализируете панель, пропускаете первую метку и в конечном итоге добавляете вторую метку.

[EDIT 3 май 2010]

Этот код работает под Visual Studio 9. (я переехал с помощью пункта)

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

результата им собирающей панель с только первой этикеткой , В ParsePanelElement я снова читаю subReader, а не оригинальное считывающее устройство. Поскольку это простой пример, вы могли бы исправить код для меня, чтобы я понял, что я делаю неправильно? – no9

+0

Я думал, что нашел проблему в ParseLabelElement. Я заменил: "reader.Read(); var myString = reader.Value as string;" на "var myString = reader.ReadElementContentAsString();". Но проблема остается, так как когда это называется, позиция читателя меняется на следующий узел (в моем случае вторая метка). Есть ли способ прочитать значение узла и оставаться на том же месте? – no9

+0

Является ли reader.Read() необходимым в этот момент? Я не могу проверить прямо сейчас, так как у меня нет Visual Studio здесь. Кажется, что в 'ParsePanelElement' вы читаете первый узел, когда' ParsePanelElement' вызывает 'ParseXml', вы читаете другой узел и когда' parseXml' вызывает 'ParseLabelElement' вы читаете другой узел. Кроме того, работает ли это с использованием инструкции? Я думал, что использование операторов работает только при объявлении в нем нового назначенного объекта? Если это сработает, это может стать причиной вашей проблемы. Оператор using закрывает subreader, поэтому петли while завершаются. – Roy

Смежные вопросы