PerlXML::细枝字符编码
我有一组XML文件,其中包含非简单ASCII字符和编码字符,例如:PerlXML::细枝字符编码,xml,perl,encoding,utf-8,Xml,Perl,Encoding,Utf 8,我有一组XML文件,其中包含非简单ASCII字符和编码字符,例如: ... many 8-bit characters such as é, ⪚, and ñ. (第二个字符是的符号和分号版本。)⪚. 第一个和第三个是未转义的角色。) 这些文件是UTF-8格式的 当我使用XML::Twig运行Perl脚本时,实体(上面的第2个字符)会变成未知字符(当它写入文件时,我会收到“打印中的宽字符”消息) 这是我的密码。处理程序所做的只是读取XML,而不是进行任何更改: my $
... many 8-bit characters such as é, ⪚, and ñ.
(第二个字符是的符号和分号版本。)⪚. 第一个和第三个是未转义的角色。)
这些文件是UTF-8格式的
当我使用XML::Twig运行Perl脚本时,实体(上面的第2个字符)会变成未知字符(当它写入文件时,我会收到“打印中的宽字符”消息)
这是我的密码。处理程序所做的只是读取XML,而不是进行任何更改:
my $twig= XML::Twig->new(
comments => 'keep',
output_encoding => 'UTF-8',
# keep_encoding => 1,
twig_handlers => { topicref => \&topicref_processing,
xref => \&topicref_processing,
link => \&topicref_processing},
pretty_print => 'indented',
);
$twig->parsefile($file);
my($outfile) = $file;
$outfile =~ s/([.]dita)/.out$1/i;
open(NEW,">$outfile");
$twig->flush( \*NEW);
close(NEW);
如果我添加keep_encoding=>1(上面已注释掉),实体将被保留,但第一个和第三个字符将被损坏:
...such as é, ⪚, and ñ.
如果我将UTF-8编码添加到刷新:
open(NEW,'>:encoding(UTF-8)', $outfile);
更奇怪的是:
...such as Ã?©, ⪚, and Ã?±.
你知道如何毫发无损地穿过人物和实体吗?
非常感谢。
Scott除了确保输入和输出IO通道设置为UTF-8编码之外,您无需做任何特殊的事情。打印中的
宽字符
警告表示您正试图将宽字符(大于255的代码点)打印到只有字节语义的通道
如果我使用这个数据
<?xml version="1.0" encoding="UTF-8"?>
<root>
<text>... many 8-bit characters such as é, ⪚, and ñ.</text>
</root>
输出
... many 8-bit characters such as é, ⪚, and ñ.
更新 这是为了解释你得到的输出 如果我添加keep_encoding=>1(上面已注释掉),实体将被保留,>但第一个和第三个字符将被损坏:
...such as é, ⪚, and ñ.
…例如λλ,⪚, ñ
这些字符没有损坏,文本输出为UTF-8,但无论您使用什么方式查看它,都需要字节编码,类似于ISO-8859-1。当编码为UTF-8时,e-acute字符U+00E9
是一个双字节字符0xC3 0xA9
。当解释为ISO-8859-1时,0xC3是A-tilde,0xA9是版权标志,这正是您所看到的。如果您使用的是预期的UTF-8编码数据,那么您将看到单字符e-acute
如果我将UTF-8编码添加到刷新:
open(NEW,'>:encoding(UTF-8)', $outfile);
打开(新的,'>:编码(UTF-8)'$outfile)
更奇怪的是:
...such as Ã?©, ⪚, and Ã?±.
…如Ã?┱,⪚, 和ñ
这里发生的事情是,虽然来自
XML::Twig
的字符串已经编码为UTF-8,但数据没有标记为UTF-8。这意味着构成UTF-8编码字符的两个字节被视为单独的字符,它们被再次编码,总共四个字符除了确保输入和输出IO通道设置为UTF-8编码之外,您无需做任何特殊的事情。打印中的宽字符
警告表示您正试图将宽字符(大于255的代码点)打印到只有字节语义的通道
如果我使用这个数据
<?xml version="1.0" encoding="UTF-8"?>
<root>
<text>... many 8-bit characters such as é, ⪚, and ñ.</text>
</root>
输出
... many 8-bit characters such as é, ⪚, and ñ.
更新 这是为了解释你得到的输出 如果我添加keep_encoding=>1(上面已注释掉),实体将被保留,>但第一个和第三个字符将被损坏:
...such as é, ⪚, and ñ.
…例如λλ,⪚, ñ
这些字符没有损坏,文本输出为UTF-8,但无论您使用什么方式查看它,都需要字节编码,类似于ISO-8859-1。当编码为UTF-8时,e-acute字符U+00E9
是一个双字节字符0xC3 0xA9
。当解释为ISO-8859-1时,0xC3是A-tilde,0xA9是版权标志,这正是您所看到的。如果您使用的是预期的UTF-8编码数据,那么您将看到单字符e-acute
如果我将UTF-8编码添加到刷新:
open(NEW,'>:encoding(UTF-8)', $outfile);
打开(新的,'>:编码(UTF-8)'$outfile)
更奇怪的是:
...such as Ã?©, ⪚, and Ã?±.
…如Ã?┱,⪚, 和ñ
这里发生的事情是,虽然来自
XML::Twig
的字符串已经编码为UTF-8,但数据没有标记为UTF-8。这意味着构成UTF-8编码字符的两个字节被视为单独的字符,它们被再次编码,总共四个字符。首先,在您的情况下,应该使用保持编码,而不是。这是一个古老的选项,可以追溯到远古时代,当时拉丁语1是一种常用的编码方式,而perl对unicode不太好。我在这里说的是5.8之前。该选项为生活在全拉丁世界的人们提供了一种处理XML的方法,而不必处理unicode。将其与utf-8数据一起使用会导致疯狂(以及您发现的编码问题)
如其他回答中所述,需要在utf8
模式下打开输出文件,无论是在open
还是通过use utf8::all代码>。这消除了宽字符
警告,并避免了更糟糕的情况,即如果输出仅包含ascii和扩展ascii字符,则输出将转换为拉丁文1(perl这样做是为了保持向后兼容性,如果从输入中删除⪚;
,则可以看到它)
完成此操作后,输出文件将以正确的utf-8格式显示,未进行扫描。如果显示不正确,可能是您的终端不支持utf-8
如果需要转义所有非ascii字符,可以使用output\u filter=>“safe”
选项,如下代码所示
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
use utf8::all; # either this or open the output file with '>:utf8'
my $file= 'test_enc.dita';
my $twig= XML::Twig->new(
comments => 'keep',
# escapes all non-ascii characters (including accented ones)
output_filter => 'safe',
twig_handlers => { topicref => \&topicref_processing,
xref => \&topicref_processing,
link => \&topicref_processing},
pretty_print => 'indented',
);
$twig->parsefile( $file);
my($outfile) = $file;
$outfile =~ s/([.]dita)/.out$1/i;
# current best practices recommend the use the 3 args form of
# open and lexical filehandles
open( my $out,'>', $outfile);
$twig->flush( $out);
close( $out);
除了keep_编码(这是一种黑客行为)之外,没有真正的方法来忠实地保存编码/非编码的字符形式。如果您确实需要将扩展ascii字符保留为字符,并将其他字符编码为数字字符实体,您将提供一个自定义函数来output\u filter
,它应该接收字符串(所有utf-8字符),并将字符串返回到输出(一些字符编码为数字实体)
也就是说,我不确定你是否需要如此忠诚