tags:

views:

17921

answers:

5
 body = "<?xml version="1.0" encoding="utf-16"?><Report> ......"

 XmlDocument bodyDoc = new XmlDocument();            
 bodyDoc.LoadXml(body);


  This fails with an XmlException "Data at the root level is invalid. Line 1, position 1."

  Any ideas?
+3  A: 

Don't get it. I tried the same here and I get no such exception. Are you sure the root tag (Report) is closed, i.e. ending with </Report>?

Here's my test code:

string body = "<?xml version=\"1.0\" encoding=\"utf-16\"?><Report> ......</Report>";

XmlDocument bodyDoc = new XmlDocument();
bodyDoc.LoadXml(body);
Dan C.
Yah, it appears to be valid XML. Are there any good tools for validating that the XML is valid?
w3.org -> http://www.w3schools.com/Dom/dom_validate.aspbrown uni -> http://www.stg.brown.edu/service/xmlvalid/
Christian Witts
i don't think this code throws the error because of what Burly said above - that .net uses utf-16 for strings and so there is no need explicitly specify utf-16.
Tone
+1  A: 

I figured it out. Read the MSDN documentation and it says to use .Load instead of LoadXml when reading from strings. Found out this works 100% of time. Oddly enough using StringReader causes problems. I think the main reason is that this is a Unicode encoded string and that could cause problems because StringReader is UTF-8 only.

MemoryStream stream = new MemoryStream();
            byte[] data = body.PayloadEncoding.GetBytes(body.Payload);
            stream.Write(data, 0, data.Length);
            stream.Seek(0, SeekOrigin.Begin);

            XmlTextReader reader = new XmlTextReader(stream);

            // MSDN reccomends we use Load instead of LoadXml when using in memory XML payloads
            bodyDoc.Load(reader);
Reading the MSDN documentation for XmlDocument.LoadXml(String) here: http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.loadxml.aspx the method summary states: "Loads the XML document from the specified string." However, as you stated, it Does say: "If you want to load from a Stream, String, TextReader, or XmlReader, use the Load method instead of this method." Additionally, if you look at XmlDocument.Load(String) it says: URL for the file containing the XML document to load. "The URL can be either a local file or an HTTP URL (a Web address)." (more coming in another comment)
Burly
I believe the intended purpose of the line "If you want to load from a Stream, String, ..." is actually "If you want to load from a Stream, File, ..." but they have String because loading from a File takes a string parameter for the filename. I don't believe their intention is "if you want to load an XmlDocument from an in-memory string, use Load". After all, that is the stated purpose of LoadXml(String)! While your solution does provide a work around, I don't think it addresses the actual stated problem (which I'm having as well) with XmlDocument.LoadXml(String).
Burly
A: 

This is a very good question.

I constantly get the same problem, as I work with xml web services. I will give the above a go!

dotnetdev
+10  A: 

Background

Although your question does have the encoding set as UTF-16, you don't have the string properly escaped so I wasn't sure if you did, in fact, accurately transpose the string into your question.

I ran into the same exception:

System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

However, my code looked like this:

string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<event>This is a Test</event>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);

The Problem

The problem is that strings are stored internally as UTF-16 in .NET however the encoding specified in the XML document header may be different. E.g.:

<?xml version="1.0" encoding="utf-8"?>

From the MSDN documentation for String here:

Each Unicode character in a string is defined by a Unicode scalar value, also called a Unicode code point or the ordinal (numeric) value of the Unicode character. Each code point is encoded using UTF-16 encoding, and the numeric value of each element of the encoding is represented by a Char object.

This means that when you pass XmlDocument.LoadXml() your string with an XML header, it must say the encoding is UTF-16. Otherwise, the actual underlying encoding won't match the encoding reported in the header and will result in an XmlException being thrown.

The Solution

The solution for this problem is to make sure the encoding used in whatever you pass the Load or LoadXml method matches what you say it is in the XML header. In my example above, either change your XML header to state UTF-16 or to encode the input in UTF-8 and use one of the XmlDocument.Load methods.

Below is sample code demonstrating how to use a MemoryStream to build an XmlDocument using a string which defines a UTF-8 encode XML document (but of course, is stored a UTF-16 .NET string).

    string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<event>This is a Test</event>";

    // Encode the XML string in a UTF-8 byte array
    byte[] encodedString = Encoding.UTF8.GetBytes(xml);

    // Put the byte array into a stream and rewind it to the beginning
    MemoryStream ms = new MemoryStream(encodedString);
    ms.Flush();
    ms.Position = 0;

    // Build the XmlDocument from the MemorySteam of UTF-8 encoded bytes
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load(ms);
Burly
A: 

Try this:

XmlDocument bodyDoc = new XmlDocument();
bodyDoc.XMLResolver = null;
bodyDoc.Load(body);
ilie