【问题标题】:XmlDocument.Load fails, LoadXml works:XmlDocument.Load 失败,LoadXml 工作:
【发布时间】:2011-09-21 18:05:01
【问题描述】:

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

显而易见的解决方案是:

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 htmlencodes 有可能吗?

标签: c# load xmldocument xmlexception


【解决方案1】:

WebClient 使用 HTTP 响应标头中的编码信息来确定正确的编码(在这种情况下,ISO-8859-1 基于 ASCII,即每个字符 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

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

【讨论】:

  • 查看代码,似乎 Load 实例化了一个 XmlTextReader,但没有尝试设置编码。
  • @spender 是的,我环顾了 ILSpy 内部,但很难确切地看到发生了什么 - 不过有趣的问题,我喜欢回答这个问题! :-)
【解决方案2】:

Umidità 字符串作为节点内部文本必须在 这不会在 XmlDocument.Load 中给出任何错误。

【讨论】:

  • 这个问题不是关于如何修复 XML,而是为什么我上面的问题中概述的两种方法的行为不同。
  • 实际上 CDATA 标签向解析器指示字符数据,因此 XML 构造(如“
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多