修正XML编码
我有一个XML文件,里面的编码标签写的是'utf-8',但实际上它是iso-8859-1编码的。
我想知道,怎么用编程的方法在Perl和Python中检测到这一点?还有,怎么用不同的编码来解码呢?
在Perl中,我试过
$xml = decode('iso-8859-1',$file)
但是,这个方法不管用。
3 个回答
无论使用什么编程语言,基本步骤都是一样的:
首先,打开你的文件,把里面的原始字节读到一个字符串里。
然后,尝试把这些原始字节按UTF-8格式解码,同时要选择一个选项来检查是否有错误,如果不是有效的UTF-8,就会报错。
如果一个有意义的Unicode文本文件长度适中,并且是用ISO-8859-1编码的,那么它通过这个UTF-8测试的可能性非常小(当然,如果是ASCII编码,那就没问题,因为ASCII是ISO-8859-1和UTF-8的子集)。
如果测试失败了,去掉XML声明(如果有的话)。然后在前面加上这个:
<?xml version="1.0" encoding="ISO-8859-1"?>
顺便问一下,你确定你手里的数据是ISO-8859-1编码的,而不是来自Windows平台的CP1252编码吗?
当然,找到并解决数据损坏的根本原因,总是比事后再去检测和修复要好。
除此之外,主要要说明的是,你的文件并不是XML格式,所以不能用XML工具来修复它。你需要从字符或二进制的层面去处理。正如其他人所说,第一步是确认它不是有效的UTF-8编码;第二步是去掉错误的XML声明,并用正确的替换掉。这两步应该都不会太难。
错误编码是很难发现的,因为随机的二进制数据在很多编码方式中往往都能表示有效的字符串。
在Perl中,你可以尝试把它解码为utf-8格式,然后检查是否有失败的情况。这种方法是有效的,因为utf-8编码的西方语言文档几乎总是也是有效的iso-8859-1文档。
my $xml = eval { decode_utf8( $file, FB_CROAK ) };
if ( $@ ) { is_probably_iso-8859-1_instead }
现在你已经发现了问题,就需要想办法解决它。这通常取决于你使用的解析库,但有一些通用的方法可以适用。
如果没有XML声明或MIME类型,Perl会使用本地编码,所以你复制的代码应该能解决这个问题。
如果XML声明有误,你可以使用你的XML解码库提供的任何功能来覆盖它,或者在交给它之前手动替换掉这个声明。
# assuming it's on line 1:
$contents =~ s/.*/<?xml version="1.0" encoding="ISO-8859-1"?>/;