XmlDocument.Load失败,LoadXml工作:

在回答这个问题时 ,我遇到了一个我不理解的情况。 OP正在尝试从以下位置加载XML: http : //www.google.com/ig/api?weather = 12414&hl =

明显的解决方案是:

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位。

它似乎在Umidità上窒息。

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声明省略了编码。

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

它看起来像XmlDocument.Load不使用此信息,因为xml声明中也缺少编码,它必须猜测编码并使其出错。 一些挖掘让我相信它选择了UTF-8。

如果我们想要获得真正技术性的话,它所引发的字符是“à”,即ISO-8859-1编码中的0xE0,但这不是UTF-8的有效字符 – 特别是该字符的二进制表示是:

 11100000 

如果您仔细阅读UTF-8维基百科文章,我们可以看到这表明代码点(即字符)由总共3个字节组成,采用以下格式:

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

但是,如果我们回顾一下文档,接下来的两个字符是“:”,即ISO-8859-1中的0x3A和0x20。 这意味着我们最终得到的是:

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

序列的第2个或第3个字节都没有10作为两个最高有效位(这表示继续),因此这个字符在UTF-8中没有意义。

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