XmlDocument.Load失败,LoadXml工作:

问题描述:

在回答this question时,我遇到了一个我不明白的情况。该OP试图从以下位置加载XML:http://www.google.com/ig/api?weather=12414&hl=itXmlDocument.Load失败,LoadXml工作:

显而易见的解决方案是:

string m_strFilePath = "http://www.google.com/ig/api?weather=12414&hl=it"; 
XmlDocument myXmlDocument = new XmlDocument(); 
myXmlDocument.Load(m_strFilePath); //Load NOT LoadXml 

但是这个失败

XmlException:在给定的编码字符无效。第1行,位置499.

它似乎在的à窒息。

OTOH,以下工作正常:

var m_strFilePath = "http://www.google.com/ig/api?weather=12414&hl=it"; 
string xmlStr; 
using(var wc = new WebClient()) 
{ 
    xmlStr = wc.DownloadString(m_strFilePath); 
} 
var xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(xmlStr); 

我被这个困惑。任何人都可以解释为什么前者失败,但后者工作正常吗?

值得注意的是,文档的xml声明省略了编码。

+0

WebClient htmlencodes有可能吗? – Nicolai

WebClient使用在HTTP响应的报头中的编码信息,以确定正确的编码(在这是基于ASCII这种情况下ISO-8859-1,即8每个字符的比特)

它看起来像XmlDocument.Load不使用这个信息和编码也是从xml声明中丢失的,它必须在编码时猜测并得到错误。一些挖掘导致我相信它选择UTF-8。

如果我们想获得真正的技术,它抛出的字符是“à”,即ISO-8859-1编码中的0xE0,但这不是UTF-8中的有效字符 - 具体来说,这个人物是:

11100000 

如果你有一个周围挖在UTF-8 Wikipedia article我们可以看到,这表明一个代码点(即字符)组成的共3个字节采取以下格式:

Byte 1  Byte 2  Byte 3 
----------- ----------- ----------- 
1110xxxx 10xxxxxx 10xxxxxx 

但是,如果我们有一个回顾文档后面的两个字符是“:”,它是ISO-8859-1中的0x3A和0x20。这意味着我们实际上最终得到的是:

Byte 1  Byte 2  Byte 3 
----------- ----------- ----------- 
11100000 00111010 00100000 

无论是顺序的第二或第三个字节具有10作为两个最显著位(这将表明继续),所以这种性格使得没有任何意义UTF-8。

+0

现在打开Reflector ... – spender

+0

查看代码,看起来Load实例化了一个'XmlTextReader',但没有尝试设置编码。 – spender

+0

@spender是的,我看了一下ILSpy里面的内容,但很难看清究竟发生了什么 - 有趣的问题,但我喜欢回答这个问题!:-) – Justin

Umidità字符串作为节点innertext必须在<! [CDATA [Umidità]]>这不会在XmlDocument.Load中给出任何错误。

+0

这个问题不是关于如何修复XML,而是为什么我上面的问题中概述的两种方法的行为不同。 – spender

+1

事实上,CDATA标记向分析器指示字符数据,以便XML构造(如“ Justin