在XmlReader中使用它之前,是否有任何简单/通用的方法来清理基于XML的数据源,以便我可以优雅地使用不符合XML上的十六进制字符限制的XML数据?
注意:
-
该解决方案需要处理使用UTF-8以外的字符编码的XML数据源,例如:通过在XML文档声明中指定字符编码 . 在剥离无效的十六进制字符时,不破坏源的字符编码一直是一个主要的难点 .
-
删除无效的十六进制字符应仅删除十六进制编码值,因为您经常可以在数据中找到碰巧包含字符串的href值,该字符串将是十六进制字符的字符串匹配 .
背景:
我需要使用符合特定格式的基于XML的数据源(想想Atom或RSS提要),但希望能够使用已发布的数据源,这些数据源包含符合XML规范的无效十六进制字符 .
在.NET中,如果您有一个表示XML数据源的Stream,然后尝试使用XmlReader和/或XPathDocument对其进行解析,则会由于在XML数据中包含无效的十六进制字符而引发异常 . 我目前解决此问题的尝试是将Stream解析为字符串并使用正则表达式删除和/或替换无效的十六进制字符,但我正在寻找更高性能的解决方案 .
13 回答
您可以使用以下内容传递非UTF字符:
试试PHP吧!
它是 may not be perfect (重点是因为人们错过了这个免责声明),但我在这种情况下所做的就是下面 . 您可以调整以使用流 .
我喜欢Eugene的白名单概念 . 我需要做与原始海报类似的事情,但我需要支持所有Unicode字符,而不仅仅是0x00FD . XML规范是:
Char =#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
在.NET中,Unicode字符的内部表示只有16位,因此我们可以明确地使用't `allow' 0x10000-0x10FFFF . XML规范明确禁止出现从0xD800开始的代理代码点 . 但是,如果我们在白名单中使用这些代理代码点,utf-8编码,我们的字符串可能最终会生成有效的XML,只要从utf-16字符的代理对中生成正确的utf-8编码即可 . .NET字符串 . 我没有't explored this though, so I went with the safer bet and didn'允许我的白名单中的代理人 .
虽然Eugene的解决方案中的注释具有误导性,但问题是我们排除的字符在XML中无效......它们是完全有效的Unicode代码点 . 我们不会删除“非utf-8字符” . 我们正在删除可能不会出现在格式良好的XML文档中的utf-8字符 .
作为删除无效XML字符的方法,我建议您使用XmlConvert.IsXmlChar方法 . 它是从.NET Framework 4开始添加的,也是在Silverlight中呈现的 . 这是一个小样本:
DRY实现this answer的解决方案(使用不同的构造函数 - 随意使用您在应用程序中需要的那个):
现代化dnewcombe's答案,你可以采取一种稍微简单的方法
或者,与Linq
我很想知道这些方法的性能如何比较,以及它们如何与使用
Buffer.BlockCopy
的黑名单方法进行比较 .这是dnewcome在自定义StreamReader中的答案 . 它只是包装一个真正的流阅读器,并在阅读时替换它们 .
我只实现了一些方法来节省自己的时间 . 我将它与XDocument.Load和文件流结合使用,只调用了Read(char [] buffer,int index,int count)方法,因此它的工作原理如下 . 您可能需要实现其他方法才能使其适用于您的应用程序 . 我使用这种方法,因为它似乎比其他答案更有效 . 我也只实现了一个构造函数,你显然可以实现你需要的任何StreamReader构造函数,因为它只是一个传递 .
我选择替换字符而不是删除它们,因为它极大地简化了解决方案 . 这样,文本的长度保持不变,因此不需要跟踪单独的索引 .
基于正则表达式的方法
}
有关详细信息,请参阅我的blogpost
上述解决方案似乎是在转换为XML之前删除无效字符 .
使用此代码从XML字符串中删除无效的XML字符 . 例如 . &X1A;
http://balajiramesh.wordpress.com/2008/05/30/strip-illegal-xml-characters-based-on-w3c-standard/
由Neolisk above修改的答案或原始答案 .
更改:传递\ 0字符,删除完成,而不是替换 . 另外,使用了XmlConvert.IsXmlChar(char)方法
使用此函数删除无效的xml字符 .