C# 尽管进行了编码,XML解析器还是会被困在特殊字符上

C# 尽管进行了编码,XML解析器还是会被困在特殊字符上,c#,xml,C#,Xml,情况就是这样: 我正在从一个XMLAPI接收数据。这些数据有时包含一个特殊的撇号字符,这会导致解析器崩溃。只有从本地文件读取数据时,才会发生此崩溃。当我从流中读取数据时,没有崩溃,但是我也没有得到DOM树:它在没有通知我的情况下退出 下面,您将看到我们为使事情正常运行所做的尝试列表: // Does not work var web = new WebClient(); web.Encoding = Encoding.UTF8; var response = web.DownloadString

情况就是这样:

我正在从一个XMLAPI接收数据。这些数据有时包含一个特殊的撇号字符,这会导致解析器崩溃。只有从本地文件读取数据时,才会发生此崩溃。当我从流中读取数据时,没有崩溃,但是我也没有得到DOM树:它在没有通知我的情况下退出

下面,您将看到我们为使事情正常运行所做的尝试列表:

// Does not work
var web = new WebClient();
web.Encoding = Encoding.UTF8;
var response = web.DownloadString("http://thetvdb.com/api/apikey/series/" + show.TVDBID + "/");
var tree = XDocument.Parse(response);

// Works
var doc = new XmlDocument();
doc.Load("C:\\Test\\test.xml");
var response = doc.InnerXml;
var tree = XDocument.Parse(response);

// Works
var xmlDoc = XDocument.Parse(File.ReadAllText("c:\\Test\\test.xml", System.Text.Encoding.UTF8));
var xmlDoc = XDocument.Load("C:\\Test\\test.xml");
var tree = xmlDoc;

// Does not work
var web = new WebClient();
web.Encoding = Encoding.UTF8;
web.DownloadFile("http://thetvdb.com/api/apikey/series/" + show.TVDBID + "/", "C:\\test.xml");
var tree = XDocument.Load("C:\\test.xml");

// Does not work
var web = new WebClient();
web.Encoding = Encoding.UTF8;
var data = web.DownloadData("http://thetvdb.com/api/apikey/series/" + show.TVDBID + "/");
var response = Encoding.UTF8.GetString(data);
var tree = XDocument.Parse(response);
我根据某个对象是否到达循环第一行中的断点来确定它是否工作:

if (root != null) { 
     var lastupdate = root.Element("Series").Element("lastupdated").Value;

     foreach (var epi in tree.Descendants("Episode")) {
          var season = epi.Element("SeasonNumber").Value; // Breakpoint here
     }
}
当解析器遇到以下撇号时会发生崩溃:

当我用自己手动输入的撇号或
'
替换此字符时,不会再抛出错误,它会一直持续到下一个错误。 当我在firefox和chrome中查看API请求的源页面时,它告诉我编码是UTF-8,API wiki上的代码示例也在标题中显示UTF-8

到目前为止,我就在这里。有什么想法吗

我刚刚注意到,根据调试期间的XML/Text/HTML可视化工具,来自API查询的结果字符串只包含一个
标记,没有
标记。但是,当我在浏览器中执行相同的查询时,它会同时显示这两个查询。这可能吗?当我通过邮递员看它的时候,它显示了这些片段

更新:

当我使用Unicode作为编码时,我不会收到任何警告,并且我能够完全解析本地xml文件!我不是编码专家,使用Unicode有什么缺点吗

在数据流中使用unicode时,我会得到一堆亚洲字符。

试试看

var tree = XElement.Parse(response);
foreach(var epi in tree.Descendants("Episode"))
{
   ...
}

如果数据是根节点,并且没有隐藏的插曲,则可以用元素替换子体。

这与数据的编码有关。这允许您获取原始二进制文件(因此编码没有问题)

编辑根据您最近对Unicode的开发,我想说的是数据实际上是用UTF-16编码的。Unicode不是一种编码类型,它本质上只是一个编码字符集,即一组字符以及字符与表示它们的整数代码点之间的映射。“用Unicode编码”通常指UTF-16。不管怎样,很高兴你的问题解决了

'
是特定浏览器的html转义。使用
&apos

看起来你很可能被一款恼人的微软产品“聪明地引用”了,它将你所有的引号和撇号都改成了卷曲的,声称是ISO-8859-1/Latin-1,但实际上是Win-1252,缺少C0平面。如果是这样的话,只有Win-1252is编码将为您解析该文档。或者你可以把卷曲的apos换成普通的,一切都会好起来。

我已经找到了解决办法,这有点反气候。因为我的API字符串不完整,所以没有检索到这些片段:它应该以
/all/
结尾,但我一定是在某个地方忘记了它,并从此点开始复制。那是我最后一次找的地方

通过更改API调用,我现在可以检索所有剧集。 没有更多的编码错误(即使我没有对此做任何更改),现在它已经检索到4000集,所以我假设其余的也不会出现问题


有人把它变成了一个社区维基:我不确定这种状态是否仍然有效,因为这是一个本地化的问题。不过,我从这些对话中学到了很多关于XML/API的知识,感谢大家

您如何实例化
变量?@BenReich:我已经用代码编辑了我的帖子。@如果您将XML结构/数据发布到代码标记中,而不是人们可以用来制作自己的样本以帮助您的图像中,Jeroenvanevel会更有用。@Prix:我添加了一个指向XML代码的链接。您发布到pastebin的XML是缺少结束标记。
子体
返回一个
IEnumerable
集合-如何将其转换为通用列表?这是一个不必要的步骤。@Tim这取决于OP在循环中执行的操作,例如删除元素。我已经尝试过了,但没有什么不同。循环的代码可以在OP中的edit 4中找到。它所做的只是检索值,创建一个匿名对象,并用此调用存储库。仅读取DOM上的操作。@Tim也可以,如果他正在设置一个断点,但没有.ToList(),它可能永远不会执行,因为枚举的延迟执行。@ChuckSavage-我能够在没有.ToList()的情况下使断点工作。我希望for each循环枚举可枚举项,尽管我可能错了。比如什么?XML是一个API响应,我无法控制它。当我使用本地文件并在顶部添加这一行时,它仍然不起作用。utf-8不是编码。然后,用浏览器打开XML,转到菜单上的“查看”,然后转到“文本编码”或“字符编码”,查看勾选的内容。同时,如果这不起作用,试着用';看看它是否有效。我应该在哪里检查文本编码?我使用了
查看源代码
,它显示了我在上面键入的编码。我已经按照你的建议做了,并且替换工作正常:错误被抛出到行中的下一个字符。我用n++打开了xml文件,将编码设置为UTF-8,它会在错误重音应该出现的地方显示编码错误(
x92
)。这是因为API没有用UTF-8编码文件,如果没有指定编码,大多数解析器默认使用UTF-8(这是您的情况)。理想情况下,您最好了解API使用的编码是什么,以便可以将其添加到文件的顶部。我的建议是:不在顶部添加行,用浏览器打开XML。眉头
WebClient myWebClient = new WebClient();
byte[] data = myWebClient.DownloadData(uri);

string xmlContents = Encoding.UTF8.GetString(data);