none
Error with XmlReader: Root element is missing

    Question

  • Hello,

    I am trying to read an xml file. I have to scan the file two times.
    The first time works fine but when I try to scan it the second time, it throws the exception: Exception: Root element is missing. Type:System.Xml.XmlException

    My code is:

                    System.IO.StreamReader reader <- The function receives this parameter


                    XmlReader xReader =  XmlReader.Create(reader);
                   
                   
                    while(xReader.Read())
                        string test = xReader.ReadOuterXml();   ------> This works fine, it shows the xml file

                    xReader.Close();
                    xReader = null;
                    xReader = XmlReader.Create(reader);         -----> I want to read again from the beginning. So the cursor mus be located at the first position
                   
                       
                        while(xReader.Read())                                      --> EXCEPTION: Root element is missing. But the xml file is the same!!!
                            string test2 =  xReader.ReadOuterXml(); 


    Do you know what the problem could be?

    Thanks a lot!
     
    Tuesday, August 11, 2009 10:06 PM

All replies

  • Hi Johannes,
    the base stream is not reset when you create the XmlReader. The fist time everything works as intended, but the second time you are starting to read from the point where you left off the last time, i.e. the end of the stream. Hence the exception.

    The solution is rather simple: reset the file position before you try to read for the second time...

    reader.BaseStream.Position = 0;
    XmlReader xReader = XmlReader.Create (reader);
    ...

    HTH
    --mc
    • Proposed as answer by Rezastro Thursday, November 04, 2010 3:29 PM
    Tuesday, August 11, 2009 10:32 PM
  • Hello Mario!

    thank you for your reply!

    I have tested but it does not work yet. The exception has changed and now it says: XmlException: The data at the root level is invalid. Line 1, position 1.

    I did exactly what you said to me. I put it the BaseStream.Position = 0

    Any ideas?

    Thank you!
    Wednesday, August 12, 2009 2:01 PM
  • Johannes,
    I tested locally with a number of xml files and it worked fine.
    The most likely explanation I can think of is that the XML may not be located at the beginning of the file, so resetting the base stream position to 0 would be inappropriate in this case.

    To find out if this is the case (and correct the issue) you can try something like this:

    public void ReadXmlTwice (StreamReader reader) {
      long startPosition = reader.BaseStream.Position;
      
      XmlReader xmlReader = new xmlReader (reader);
     
      while (xmlReader.Read ()) {
        ...
      }

      reader.BaseStream.Position = startPosition;
      xmlReader = new xmlReader (reader);
     
      while (xmlReader.Read ()) {
        ...
      }
    }

    If this still does not work, it would help if you could post a sample XML file.

    HTH
    --mc

    Wednesday, August 12, 2009 2:26 PM
  • Hallo Mario,

    thank you for your answer.

    It is really strange, if it works fine... In my case, it does not :-(

    I have copied the function, like you told me:

    public void ReadXmlTwice (StreamReader reader) {
               
                  long startPosition = reader.BaseStream.Position;
                 
                  XmlReader xmlReader = XmlReader.Create (reader);
                 
                  while (xmlReader.Read ()) {
                      string firsttime = xmlReader.Name;
                  }
               
                  reader.BaseStream.Position = startPosition;           ----------> Position is 0 (zero)
                  xmlReader = XmlReader.Create (reader);
                 
                  while (xmlReader.Read ()) {                           ------------> Here it is the exception:  XmlException: The data at the root level is invalid. Line 1, position 1.
                      string secondtime = xmlReader.Name;
                  }
            }


    The content from the xml file is very simple:
    <?xml version="1.0" encoding="utf-8"?>
    <note>
        <to>Tove</to>
        <from>Jani</from>
        <heading>Reminder</heading>
        <body>Don't forget me this weekend!</body>
    </note>

    The first time works fine but the second time. At the beginning there are not blanks

    Thank you again!



    Wednesday, August 12, 2009 2:59 PM
  • Hi JohannesM

    What version of .NET Framework are you using?
    If you create another xml file, does the problem recur?

    Thanks.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, August 18, 2009 3:32 AM
  • Hi,

    Although it should be functionally equivalent, please try replacing the

    reader.BaseStream.Position = startPosition;

    with

    reader.BaseStream.Seek(startPosition, System.IO.

    SeekOrigin.Begin);

    That *might* help, although like I said, internally it should amount to the same thing as the previous suggestion.

    If that doesn't work, just to be totally sure, please try

    reader.BaseStream.Seek(0, System.IO.SeekOrigin.Begin);

    Finally, if that doesn't work it could be the stream is being disposed when the first reader is garbage collected (unlikely given how close together the lines are, but possible given the reference to it is being released when the second reader is assign to the same variable), in this case assign the second reader to a new variable, i.e

    public void ReadXmlTwice (StreamReader reader) {
               
                  long startPosition = reader.BaseStream.Position;
                 
                  XmlReader xmlReader = XmlReader.Create (reader);
                 
                  while (xmlReader.Read ()) {
                      string firsttime = xmlReader.Name;
                  }
               
                  reader.BaseStream.Position = startPosition;           
                  XmlReader secondReader = XmlReader.Create (reader);
                 
                  while (secondReader.Read ()) {                           
                      string secondtime = secondReader.Name;
                  }
            }

    You should also close both readers when you are done with them.

    Tuesday, August 18, 2009 4:01 AM
  • The file probably has the optional 3 byte preamble. Not shown here because they are control chars.

    var optionalPreamble=reader.CurrentEncoding.GetPreamble();
    reader.BaseStream.Seek((optionalPreamble == null) ?
    0 : optionalPreamble.Length, SeekOrigin.Begin);
    reader.DiscardBufferedData();

    Wednesday, October 17, 2012 3:53 PM