给定Stream作为输入,如何安全地针对XML数据源创建XPathNavigator?
XML数据源:
例如,云中的某些XML数据源将具有 utf-8 的声明编码,但实际编码为 windows-1252 或 ISO 8859-1 ,在针对Stream创建XmlReader时可能导致无效的字符异常被抛出。
来自 StreamReader.CurrentEncoding 属性文档:“当前读者使用的当前字符编码。在第一次调用StreamReader的任何Read方法后,该值可能会有所不同,因为编码自动检测不是完成,直到第一次调用Read方法。“这似乎表明可以在第一次读取后检查CurrentEncoding,但是当我们需要将XML数据写入Stream时,我们是否会停止存储此编码?
我希望找到一种最佳实践,以便针对XML数据源安全地创建XPathNavigator / IXPathNavigable实例,该实例将优雅地处理无效字符问题的编码(最好在C#中)。
答案 0 :(得分:2)
当使用错误的编码将一些XML片段导入CRM系统时,我遇到了类似的问题(没有与XML片段一起存储的编码)。
在循环中,我使用列表中的当前编码创建了一个包装器流。使用DecoderExceptionFallback和EncoderExceptionFallback选项(如@Doug所述)构造编码。如果在处理期间抛出了DecoderFallbackException,则重置原始流并使用次最可能的编码。
我们的编码列表类似于UTF-8,Windows-1252,GB-2312和US-ASCII。如果你从列表的末尾掉下来,那么流就非常糟糕,被拒绝/忽略/等等。
编辑:
我发了一个快速示例和基本测试文件(来源here)。代码在两个匹配相同字节集的代码页之间没有任何启发式选择,因此Windows-1252文件可能被检测为GB2312,反之亦然,具体取决于文件内容和编码首选项顺序。 / p>
答案 1 :(得分:1)
可以使用DecoderFallback类(以及一些相关的类)来处理坏字符,可以通过跳过它们或通过执行其他操作(使用新编码重新启动?)。
答案 2 :(得分:0)
当使用XmlTextReader或类似的东西时,阅读器本身将找出xml文件中声明的编码。