如何从输入流中删除重音字符
我正在尝试使用 Pull 解析器解析 Android 上的 Rss2.0 提要。
XmlPullParser parser = Xml.newPullParser();
parser.setInput(url.open(), null);
feed XML 的序言表明编码是“utf-8”。当我打开远程流并将其传递给我的拉解析器时,我得到无效的令牌,文档格式不正确的异常。
当我保存 XML 文件并在浏览器 (FireFox) 中打开它时,浏览器报告文件中存在 Unicode 0x12 字符(重音符号?),并且无法呈现 XML。
假设我无法控制返回的 XML,处理此类情况的最佳方法是什么?
谢谢。
I am trying to parse a Rss2.0 feed on Android using a Pull parser.
XmlPullParser parser = Xml.newPullParser();
parser.setInput(url.open(), null);
The prolog of the feed XML says the encoding is "utf-8". When I open the remote stream and pass this to my Pull Parser, I get invalid token, document not well formed exceptions.
When I save the XML file and open it in the browser(FireFox) the browser reports presence of Unicode 0x12 character(grave accent?) in the file and fails to render the XML.
What is the best way to handle such cases assuming that I do not have any control over the XML being returned?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你在哪里发现0x12是重音符号? UTF-8 的字符范围 0x00-0x7F 与 ASCII 编码相同,ASCII 代码点 0x12 是控制字符、DC2 或 CTRL+R。
这听起来像是某种编码问题。解决此问题的最简单方法是查看在十六进制编辑器中保存的文件。有一些事情需要检查:
如果您可以将文件上传到pastebin或类似的地方,我可以帮助找到原因并提出解决方案。
编辑:好的,您无法上传。这是可以理解的。
您获得的 XML 不知何故已损坏,理想的做法是联系负责生成该 XML 的一方,看看问题是否可以解决。
不过,在执行此操作之前需要检查一件事 - 您确定获得的数据不受干扰吗?某些形式的通信 (SMS) 仅允许 7 位字符。这会将 0x92(ASCII 正向记号/撇号 - 重音符号?)转换为 0x12。看起来很巧合,特别是如果这些出现在您期望有重音的文件中。
否则,您将不得不尽力利用您所拥有的:
虽然不是绝对必要的,但要采取防御措施并将“UTF-8”作为第二个参数传递给解析器上的
setInput
.类似地,通过传递不同的编码作为第二个参数来强制解析器使用另一种字符编码。除了“UTF-8”之外,还可以尝试的编码是“iso-8859-1”和“UTF-16”。
作为最后的手段,您可以删除无效字符,例如删除 0x20 以下的非空白字符(0x9、0xA 和 0xD 都是空白字符) .) 如果删除它们很困难,您可以替换它们。
例如,
您将其包装在现有的输入流中,它会过滤掉无效字符。请注意,您可能很容易对 XML 造成更多损坏,或者最终得到无意义的 XML,但同样它可以让您获取所需的数据或更容易地发现问题所在。
Where did you find that 0x12 is the grave accent? UTF-8 has the character range 0x00-0x7F encoded the same as ASCII, and ASCII code point 0x12 is a control character, DC2, or CTRL+R.
It sounds like an encoding problem of some sort. The simplest way to resolve that is to look at the file you've saved in a hex editor. There are some things to check:
If you can upload the file to pastebin or similar, I can help find the cause and suggest a resolution.
EDIT: Ok, you can't upload. That's understandable.
The XML you're getting is corrupted somehow, and the ideal course of action is to contact the party responsible for producing it, to see if the problem can be resolved.
One thing to check before doing that though - are you sure you are getting the data undisturbed? Some forms of communication (SMS) allow only 7-bit characters. This would turn 0x92 (ASCII forward tick/apostrophe - grave accent?) into 0x12. Seems like quite a coincidence, particularly if these appear in the file where you would expect an accent.
Otherwise, you will have to try to make best do with what you have:
although not strictly necessary, be defensive and pass "UTF-8" as the second paramter to
setInput
, on the parser.similarly, force the parser to use another character encoding by passing a different encoding as the second parameter. Encodings to try in addtion to "UTF-8" are "iso-8859-1" and "UTF-16". A full list of supported encodings for java is given on the Sun site - you could try all of these. (I couldn't find a definitive list of supported encodings for Android.)
As a last resort, you can strip out invalid characters, e.g. remove all characters below 0x20 that are not whitespace (0x9,0xA and 0xD are all whitepsace.) If removing them is difficult, you can replace them instead.
For example
You wrap this around your existing input stream, and it filters out the invalid characters. Note that you could easily do more damage to the XML, or end up with nonsense XML, but equally it may allow you to get out the data you need or to more easily see where the problems lie.
我用正则表达式来过滤它,但诀窍不是试图获取和替换重音符号。这取决于编码,您不想更改内容。
尝试将标签的内容插入到此标签中
Like this
To this
正则表达式应该不难理解。它对我有用,希望对你有帮助。
I use to filter it with a regex, but the trick is not trying to get and replace the accents. It depends on the encode and you don't want to change the content.
Try to insert the content of the tags into this tags
Like this
To this
The regex shouldn't be very hard to figure out. It works for me, hope it helps for you.
UTF-8 的问题在于它是一种多字节编码。因此,它需要一种方法来指示字符何时由多个字节(可能是两个、三个、四个……)组成。这样做的方法是保留一些字节值来表示多字节字符。因此,编码遵循一些基本规则:
您的问题是您可能正在读取一些据称编码为 UTF-8 的字符串(如XML 编码定义指出),但字节块可能并未真正以 UTF-8 进行编码(将某些内容声明为 UTF-8 但使用不同的编码(例如 Cp1252)对文本进行编码是一个常见的错误)。您的 XML 解析器尝试将字节块解释为 UTF-8 字符,但发现一些不符合编码规则的内容(非法字符)。即设置两个最高有效字节的两个字节将带来非法编码错误:110xxxxx 后面必须始终跟有 10xxxxxx(诸如 01xxxxxx 11xxxxxx 00xxxxxx 之类的值将是非法的)。
当使用非可变长度编码时,不会出现此问题。即,如果您在 XML 声明中声明您的文件使用 Windows-1252 编码,但最终使用 ANSI,那么您唯一的问题将是非 ASCII 字符(值 > 127)将无法正确呈现。
解决方案:
或者,如果您不介意非 ASCII 字符(无论是否偶尔出现奇怪的符号),您可以直接转到步骤 2并强制 XML 处理为任何 ASCII 兼容的 8 字节固定长度编码(ANSI、任何 Windows-XXXX 代码页、Mac-Roman 编码等)。使用您当前的代码,您可以尝试:
The problem with UTF-8 is that it is a multibyte encoding. As such it needs a way to indicate when a character is formed by more than one byte (maybe two, three, four, ...). The way of doing this is by reserving some byte values to signal multibyte characters. Thus encoding follows some basic rules:
Your problem is that you may be reading some character string supposedly encoded as UTF-8 (as the XML encoding definition states) but the byte chunk might not be really encoded in UTF-8 (it is a common mistake to declare something as UTF-8 but encoding text with a different encoding such as Cp1252). Your XML parser tries to interpret byte chunks as UTF-8 characters but finds something that does not fit the encoding rules (illegal character). I.e. two bytes with two most significate bytes set would bring an illegal encoding error: 110xxxxx must be always followed by 10xxxxxx (values such as 01xxxxxx 11xxxxxx 00xxxxxx would be illegal).
This problem does not arise when non-variable length encodings are used. I.e. if you state in your XML declaration that your file uses Windows-1252 encoding but you end up using ANSI your only problem will be that non-ASCII characters (values > 127) will render incorrectly.
The solution:
Alternatively if you do not mind about non-ASCII characters (no matter if strange symbols appear now and then) you could go directly to step 2 and force XML processing to any ASCII compatible 8-byte fixed length encoding (ANSI, any Windows-XXXX codepage, Mac-Roman encoding, etc.). With your present code you just could try:
调用 setInput(istream, null) 已经意味着拉解析器尝试自行检测编码。由于文件存在实际问题,它显然失败了。所以这并不是说你的代码是错误的——你不能指望能够解析所有不正确的文档,无论是格式错误还是编码错误。
但是,如果您必须尝试解析此特定文档,则可以修改解析代码,使其位于将编码作为参数并包装在 try/catch 块中的函数中。第一次时,不要指定编码,如果出现编码错误,请使用 ISO-8859-1 重新启动。如果必须成功,请对其他编码重复此操作,否则在两次后退出。
Calling
setInput(istream, null)
already means for the pull parser to try to detect the encoding on its own. It obviously fails, due to the fact that there is an actual problem with the file. So it's not like your code is wrong - you can't be expected to be able to parse all incorrect documents, whether ill-formed or with wrong encodings.If however it's mandatory that you try to parse this particular document, what you can do is modify your parsing code so it's in a function that takes the encoding as a parameter and is wrapped in a try/catch block. The first time through, do not specify an encoding, and if you get an encoding error, relaunch it with ISO-8859-1. If it's mandatory to have it succeed, repeat for other encodings, otherwise call it quits after two.
在解析 XML 之前,您可以对其进行调整,并在解析之前手动删除重音符号。
也许不是迄今为止最好的解决方案,但它可以完成任务。
Before parsing your XML, you may tweak it, and manually remove the accents before you parse it.
Maybe not the best solution so far, but it will do the job.