|
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 Silverlight quickstart 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 the unicode.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:
Use reader.ReadToFollowing("myNode"); But those first few bytes prevent me from reading anything.
I tried removing <?xml version="1.0" encoding="utf-8" ?>, but no luck
Based on an MSDN forum, I tried removing this first line: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
In the StreamReader class, I set the detectEncodingFromByteOrderMarks constructor property (trying both true and false), but no luck.
I tried modifying the Xml Reader to directly get from URI. However, I got the error: "Support for http:// URIs is not yet implemented."
I tried overloading the XmlReader with XmlReaderSettings (and setting IgnoreProcessingInstructions )
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 "<?" that starts the Xml file, and then reload that into a StringReader, and feed the StringReader into a XmLReader. Here's a static utility method that you can reuse:
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.
Did you try to read a file which contains real utf-8 characters (like Chinese characters or Romanian ă, î, ş, ţ or French, etc) - you will find out that all the utf-8 special characters get corrupted, so the problem is not actually that firefox gets 3 extra bytes, but that FF messes up completely utf-8 files. I also tried all sorts of workarounds, but there is not much to work with in silverlight, so I would really appreciate any help in solving this problem properly.