在Perl中读取和编写具有未知编码的XML文件?

时间:2011-05-27 20:14:09

标签: html xml perl utf-8 latin1

我正在挑选别人的大型项目,试图纠正错误。问题是,我只是不确定正确的方式是什么。

所以,我正在编写一堆HTML页面,然后用简单的命令将其写入文件:

$src = `curl http://google.com`;
open FILE, ">output.html";
print FILE $src;
close FILE;

现在我希望将它们保存为UTF-8。它被保存为什么?然后我使用相同的基本'open'命令读取html文件,使用regex调用解析html,并使用字符串连接创建一个大字符串并将其写入XML文件(使用与上面相同的代码)。我已经开始使用XML :: Writer了,但现在我必须修复编码不准确的文件。

所以,我没有html了,但我仍然有必须显示正确字符的XML。以下是一个示例:http://filevo.com/wkkixmebxlmh.html

主要问题是使用正确显示在编辑器中的“\ x {2019}”检测并替换相关字符。但是我无法想出一个正则表达式来实际捕捉野外角色。

更新

我仍然无法检测到我上传到Filevo的XML文件中的ALT-0146字符。我试过用UTF-8打开它,然后搜索/ \ x {/} /,/ chr(0x2019)/,只搜索/'/,没有。

3 个答案:

答案 0 :(得分:4)

发现HTML文档的编码难以。参见http://blog.whatwg.org/the-road-to-html-5-character-encoding,特别是它需要“7步算法;步骤4有2个子步骤,第一步有7个分支,其中一个有8个子步骤,其中一个实际链接到a单独的算法本身有7个步骤...它会持续一段时间。“

这是我用于解析HTML文件的有限需求。

my $CHARACTER_SET_CLASS = '\w:.()-';

     # X(HT)?ML: http://www.w3.org/International/O-charset
     /\<\?xml [^>]*(?<= )encoding=[\'\"]?([$CHARACTER_SET_CLASS]+)/ ||
     # X?HTML: http://blog.whatwg.org/the-road-to-html-5-character-encoding
     /\<meta [^>]*\bcharset=["']?([$CHARACTER_SET_CLASS]+)/i ||
     # CSS: http://www.w3.org/International/questions/qa-css-charset
     /\@charset "([^\"]*)"/ ||

答案 1 :(得分:3)

要确保以UTF-8生成输出,请使用utf8

binmode图层应用于输出流
open FILE, '>output.html';
binmode FILE, ':utf8';

或3-argument open调用

open FILE, '>:utf8', 'output.html'

任意输入比较棘手。如果幸运的话,HTML输入会在早期告诉你它的编码:

wget http://www.google.com/ -O foo ; head -1 foo

<!doctype html><html><head><meta http-equiv="content-type" content="text/html; 
charset=ISO-8859-1"><title>Google</title><script>window.google=
{kEI:"xgngTYnYIoPbgQevid3cCg",kEXPI:"23933,28505,29134,29229,29658,
29695,29795,29822,29892,30111,30174,30215,30275,30562",kCSI:
{e:"23933,28505,29134,29229,29658,29695,29795,29822,29892,30111,
30174,30215,30275,30562",ei:"xgngTYnYIoPbgQevid3cCg",expi:
"23933,28505,29134,29229,29658,29695,29795,29822,29892,30111,
30174,30215,30275,30562"},authuser:0,ml:function(){},kHL:"en",
time:function(){return(new Date).getTime()},

啊,它是:<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">。现在,您可以继续将输入读取为原始字节,并找到一些方法来使用已知编码对这些字节进行解码。 CPAN可以为此提供帮助。

答案 2 :(得分:1)

我指的是您问题的更新部分(下次open a new one指一个单独的主题)。这是你的文件的十六进制转储(请不要在将来帮助帮助者跳过燃烧的箍来获取你的示例数据):

0000  3c 78 6d 6c 3e 0d 0a 3c  70 65 72 73 6f 6e 4e 61  <xml>␍␤< personNa
0010  6d 65 3e 47 2e 20 50 65  74 65 72 20 44 61 80 41  me>G. Pe ter Da�A
0020  6c 6f 69 61 3c 2f 70 65  72 73 6f 6e 4e 61 6d 65  loia</pe rsonName
0030  3e 0d 0a 3c 2f 78 6d 6c  3e 0d 0a                 >␍␤</xml >␍␤

你说你知道这个角色应该是,但它完全被破坏了。在任何编码中它都不能是0x80。这看起来像是粘贴事故,您在编辑器/剪贴板之间传输数据而不是仅处理文件。如果情况并非如此,那么你的牛人就会产生错误,你无法在算法上做到正确。