XML::LibXML处理时é被编码为é,如何避免或解码?
问题描述
我有一个test.xml文件,内容如下:
<div value="éclair">éclair</div>
使用以下Perl代码提取并打印内容:
use strict; use XML::LibXML; use XML::LibXML::Reader; use utf8; my $parser = XML::LibXML->new(); open my $fh, "<", "test.xml"; my $reader = XML::LibXML::Reader->new(IO => $fh, recover => 1, suppress_errors => 1, huge => 1000000000); while ($reader->read) { next unless $reader->nodeType == XML::LibXML::Reader->XML_READER_TYPE_ELEMENT; next unless $reader->name eq "div"; my $html = $reader->readOuterXml; my $doc = $parser->load_xml(string => $html); print $doc->toString() . "\n"; }
但打印结果中字符é被编码为é:
<?xml version="1.0"?> <div value="éclair">éclair</div>
请问是否可以避免该编码过程?或者如何在Perl中将é解码为é?
解决方案
一、避免编码,直接输出原字符
XML::LibXML的toString()方法默认会对非ASCII字符进行实体编码,可通过以下两种方式避免:
方法1:使用toString(1)
修改打印语句为:
print $doc->toString(1) . "\n";
toString(1)启用格式化模式,默认以UTF-8编码输出,不会将ASCII范围外的字符转成实体。
方法2:显式指定输出编码
创建解析器时明确设置编码为UTF-8:
my $parser = XML::LibXML->new(encoding => 'UTF-8');
同时确保标准输出为UTF-8编码:
binmode STDOUT, ':encoding(UTF-8)'; print $doc->toString() . "\n";
这样非ASCII字符会直接以UTF-8字节输出,不会被转义为实体。
二、解码已编码的实体
如果已得到包含é这类实体的字符串,可借助HTML::Entities模块解码:
- 先安装模块(未安装时执行):
cpanm HTML::Entities
- 修改代码引入模块并解码:
use strict; use XML::LibXML; use XML::LibXML::Reader; use utf8; use HTML::Entities; # 引入解码模块 my $parser = XML::LibXML->new(); open my $fh, "<", "test.xml"; my $reader = XML::LibXML::Reader->new(IO => $fh, recover => 1, suppress_errors => 1, huge => 1000000000); while ($reader->read) { next unless $reader->nodeType == XML::LibXML::Reader->XML_READER_TYPE_ELEMENT; next unless $reader->name eq "div"; my $html = $reader->readOuterXml; my $doc = $parser->load_xml(string => $html); my $output = $doc->toString(); # 解码实体 $output = decode_entities($output); # 确保标准输出为UTF-8编码 binmode STDOUT, ':encoding(UTF-8)'; print $output . "\n"; }
执行后é会被转换为é。
内容的提问来源于stack exchange,提问作者jonah_w
相关产品推荐
相关产品推荐

