XML异常:无效字符

13
我正在处理一个小项目,该项目从长时间运行的应用程序接收字符串形式的XML数据。我尝试将这个字符串数据加载到XDocument (System.Xml.Linq.XDocument)中,然后进行一些XML操作,为数据生成xlsx文件以供报告使用。

偶尔,我会收到包含无效XML字符的数据,当我尝试将该字符串解析为XDocument时,我会遇到以下错误:

[System.Xml.XmlException] Message: '?', hexadecimal value 0x1C, is an invalid character.

由于我无法控制远程应用程序,您可能期望任何类型的字符。

我非常清楚XML有一种方法可以在其中放置字符,例如&#x1C之类的东西。

如果可能的话,我想要保留所有数据。如果不行,那就算了。


我考虑过编程编辑响应字符串,然后再次尝试重新解析,如果抛出异常,则进行修改,但我已经尝试过几种方法,似乎都没有成功。

感谢您的帮助。

代码大致如下:

TextReader  tr;
XDocument  doc;

string           response; //XML string received from server. 
... 
tr = new StringReader (response);   

try
{
    doc = XDocument.Load(tr);
}
catch (XmlException e)
{
    //handle here?
}
8个回答

22

您可以使用XmlReader并将XmlReaderSettings.CheckCharacters属性设置为false,这样就可以读取包含无效字符的XML文件。然后您可以将其导入到XmlDocument或XDocument对象中。

您可以在我的博客上了解更多信息。

要将数据加载到System.Xml.Linq.XDocument中,代码大致如下:

XDocument xDocument = null;
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false };
using (XmlReader xmlReader = XmlReader.Create(filename, xmlReaderSettings))
{
    xmlReader.MoveToContent();
    xDocument = XDocument.Load(xmlReader);
}

更多信息可以在此处找到。



11

10

您认为 这篇博客文章 中描述的内容是否有所帮助?

基本上,他创建了一个用于过滤XML流的方法。


实际上,他正在一次性地处理XML,作为一个字符串。 - Matthew Flaschen
@Matthew,是的,那个例子中他调用了.ReadToEnd(),但你也可以使用.Read()等。我猜测OP需要做你说的那样。 - Richard Morgan
那个链接非常有用。 - Meiscooldude
我刚刚注意到博客文章底部的XmlSanitizingStream。我的错误。 - Matthew Flaschen

0

如果你的输入不是XML格式,你应该使用类似Tidy或Tagsoup这样的工具来清理混乱的内容。

它们会接受任何输入并尝试从中构建一个有用的DOM树结构。

我不知道如何称呼那些有点阴暗的库。


0

垃圾进,垃圾出。如果远程应用程序向您发送垃圾,则您将得到垃圾。如果他们认为他们正在发送XML,则需要修复。在这种情况下,通过绕过他们的错误来帮助他们是没有任何好处的。

您还应确保他们认为自己正在发送什么。%1C 对他们意味着什么?他们想让它成为什么?


1
我希望我有能力修复他们的错误,但事实并非如此...这个错误来自未经过滤的用户输入...一些用户决定在其中输入一些超级奇怪的字符...而它却接受了... - Meiscooldude
我的建议是拒绝这些垃圾代码,然后生成一份报告,展示被拒绝的内容。然后每个月至少将该报告发送给有问题代码的所有者。 - John Saunders

0

在我看来,最好的解决方案是修改生成无效 XML 的代码/程序/任何东西。不幸的是,这并非总是可行的。在这种情况下,您需要在尝试加载文档之前转义所有字符 < 0x20。


0

如果您真的无法修复源XML数据,请考虑采用我在this answer中描述的方法。基本上,您需要创建一个TextReader子类(例如StripTextReader),它包装了现有的TextReader(tr)并丢弃无效字符。


你的回答意味着这些字符确实是垃圾。他所需要做的就是将它们丢弃。我建议他首先找出这些字符本应该是什么。 - John Saunders

0

虽然回答晚了,但可能对某些人有帮助。当您读取或序列化XML时,它可能在XML开头有1个不可见字符。XDocument 不喜欢这个不可见字符。

因此,在读取XML时,只需从第一个<字符开始阅读:

var myXml = XDocument.Parse(loadedString.Substring(loadedString.IndexOf("<")));

就是这样,它可以正常加载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接