Sunday, October 21, 2007

Silverlight: Read xml file in FireFox (solve "Data at the root level is invalid")

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/silverlight_read_xml_file_in_firefox_solve_data_at_the_ro.htm]

Any app eventually needs to read data; and it's very likely that for Silverlight, that data will be XML files on your web server. For example, in the real-time strategy TruckWars game, each level is stored as an XML file (named 1.xml, 2.xml, etc...). The Silverlightquickstart tutorials describe how to load an Xml file into an XmlReader (there is no XmLDocument for silverlight yet). While this works great in IE, it actually has a problem in FireFox. FF tries to read the xml file, but it starts with three extra bits used for reading the encoding type. These three extra bits screw up the XmlReader, and you get the error:

 

"Data at the root level is invalid. Line 1, position 1."

 

This has something to do with theunicode.GetPreamble().

 

Practically, there's probably some way to overload the reader class, or set something on the Xml file. But I couldn't figure that out. I tried several things:

  1. Use reader.ReadToFollowing("myNode"); But those first few bytes prevent me from reading anything.

  2. I tried removing , but no luck

  3. Based on anMSDN forum, I tried removing this first line:

  4. In the StreamReader class, I set the detectEncodingFromByteOrderMarks constructor property (trying both true and false), but no luck.

  5. I tried modifying the Xml Reader to directly get from URI. However, I got the error: "Support for http:// URIs is not yet implemented."

  6. I tried overloading the XmlReader with XmlReaderSettings (and setting IgnoreProcessingInstructions )

  7. I tried reading the first three bytes of stream to "skim off" the problem characters, but it still had the same problem

So, none of those attempts worked. Eventually, I got a work-around. I would read the entire xml file into a string, and then skip the first problem characters until I go to the "

    public static XmlReader CreateXmlReader(string strRelativePath)    {      HttpWebResponse response = null;      StreamReader sr = null;      try      {        //first create standard stream:        Uri u = new Uri(strRelativePath, UriKind.Relative);        HttpWebRequest request = new BrowserHttpWebRequest(u);        response = request.GetResponse();        Stream content = response.GetResponseStream();        sr = new StreamReader(content);        string s2 = sr.ReadToEnd();        //Skim off unicode.GetPreamble()        //In firefox, this would be first three bytes for UTF8        int intIndex = s2.IndexOf(");        s2 = s2.Substring(intIndex);        StringReader sr2 = new StringReader(s2);        return XmlReader.Create(sr2);      }      catch (Exception ex)      {        throw;  //Wrap in try catch for now. Will add better error-handling later.      }    }

This solved my problem, worked in both FireFox and IE, an performed well enough for my needs.

No comments:

Post a Comment