【问题标题】:Reading and Writing XML files with unknown encoding in Perl?在 Perl 中读取和写入编码未知的 XML 文件?
【发布时间】:2011-09-03 16:14:04
【问题描述】:

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

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

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

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

所以,我不再拥有 html,但我仍然拥有必须显示正确字符的 XML。这是一个例子:http://filevo.com/wkkixmebxlmh.html

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

更新:

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

【问题讨论】:

  • use utf8 专门用于将您的脚本的源代码视为 UTF-8 编码。它与脚本的任何输入和输出的编码(包括 STDOUT)没有任何关系。
  • 啊,谢谢你的澄清。

标签: html xml perl utf-8 latin1


【解决方案1】:

为确保以 UTF-8 生成输出,请使用 binmodeutf8 层应用于输出流

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

或在 3 参数 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 可以提供帮助。

【讨论】:

  • 如果你真的想要简单的事情,停止使用 curl 来获取 HTML。 use LWP::UserAgent; my $ua = LWP::UserAgent-&gt;new(); my $response = $ua-&gt;get('http://www.google.com'); $response-&gt;decoded_content; HTTP::Response 会根据 headers 将内容解码为 perl 内部的 unicode 字符串;然后你可以简单地对你的输出应用一个 unicode binmode,它就可以工作了。
  • 这是改进系统的好建议,但我仍然无法检测到我上传到 Filevo 的 XML 文件中的 ALT-0146 字符。我试过用 UTF-8 打开它,然后搜索 /\x{2019}/、/chr(0x2019)/ 和 /'/,什么都没有。
  • @Sho Minaminoto:当您将该文件拉入 perl 并使用正则表达式提取该字符时(因为您知道那个困难字符之前和之后的字符),它说的是什么有兴趣的样子?您可以将其打印到文件中并执行类似操作。
  • 您可以将 XML 文件作为文本文件打开并查看。它看起来像字母“a”加上一个货币符号,但这取决于我用什么编辑器打开它。
【解决方案2】:

发现 HTML 文档的编码是困难。请参阅http://blog.whatwg.org/the-road-to-html-5-character-encoding,尤其是它需要一个“7 步算法;第 4 步有 2 个子步骤,其中第一个有 7 个分支,其中一个有 8 个子步骤,其中一个实际上链接到一个单独的算法它本身有 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 "([^\"]*)"/ ||

【讨论】:

    【解决方案3】:

    我指的是您问题的更新部分(下次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。这看起来像是一个粘贴事故,您在编辑器/剪贴板之间传输数据,而不是只处理文件。如果不是这种情况,那么您的奶牛工人产生了一个您无法通过算法纠正的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-20
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多