2011-12-09 5 views
4

この質問はこの質問に関連しているとxmlファイルを書き込むためにハッシュキーを使用しているときのエンコーディング・エラーを取得:私は# utf8::upgrade($name);行のコメントを解除したり、それが動作$hash{'müller'} = 'magenta';行をコメントアウトHash keys encoding: Why do I get here with Devel::Peek::Dump two different results?
XML ::のlibxml

#!/usr/bin/env perl 
use warnings; 
use 5.014; 
use utf8; 
binmode STDOUT, ':encoding(utf-8)'; 
use XML::LibXML; 

# Hash read in from a file: 
# ... 
my %hash = ('müller' => 'green', 'schneider' => 'blue', 'bäcker' => 'red'); 
# ... 

# change or add something 
$hash{'müller'} = 'magenta'; 

# writing Hash to xml file 
my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); 
my $root = $doc->createElement('my_test'); 

for my $name (keys %hash) { 
    # utf8::upgrade($name); 
    my $tag = $doc->createElement('item'); 
    $tag->setAttribute('name' => $name); 
    my $tag_color = $doc->createElement('color'); 
    $tag_color->appendTextNode($hash{$name}); 
    $tag->appendChild($tag_color); 
    $root->appendChild($tag); 
} 
$doc->setDocumentElement($root); 
say $doc->serialize(1); 
$doc->toFile('my_test.xml', 1); 

出力:

error : string is not in UTF-8 
encoding error : output conversion failed due to conv error, bytes 0xFC 0x6C 0x6C 0x65 
I/O error : encoder error 
<?xml version="1.0" encoding="ISO-8859-1"?> 
<my_test> 
    <item name="m  
i18n error : output conversion failed due to conv error, bytes 0xFC 0x6C 0x6C 0x65 
I/O error : encoder error 

答えて

3

XML :: LibXMLによれば、'müller' eq 'müller'が真であるか偽であるかは、文字列が内部的にどのように格納されたかによって決まります。それはバグです。特に、UTF8フラグに意味を割り当てることは "The Unicode Bug"と呼ばれ、XML :: LibXMLはthis pageの "encodings support"セクションで正確に記述されています。

バグはknownですが、下位互換性のために修正することはできません。 PerlはUnicodeのバグのインスタンスを回避するために2つのツールを提供しています。

utf8::upgrade($sv); # Switch to the UTF8=1 storage format 
utf8::downgrade($sv); # Switch to the UTF8=0 storage format 

前者は、ここで使用するための適切なツールとなるでしょう。

sub _up { my ($s) = @_; utf8::ugprade($s); $s } 
$tag_color->appendTextNode(_up $hash{$name}); 

注:use utf8;をしない場合でも、あなたはutf8::upgradeを使用することができます。ソースコードがUTF-8の場合は、use utf8;を使用してください。

+0

これは正解ですが、残念なことに、多くの開発者がPerlのUnicode実装を理解するのが難しく、混乱しています(これまでのドキュメントと、現在は無関係の内部ストレージを引き続き提供するEncodeについて考えています)。 – chansen

+0

@chansen、私は混乱の最大の要因は、Perl自体が多くの場所でUnicodeのバグに苦しんでいたということです。 2番目に大きいのは、たとえそれが意味するものではないとしても、UTF8フラグは文字列内のデータ型の実際の良い指標であるということです。 – ikegami

2

私はISO-8859-1としてスクリプトを保存する場合、私はエラーを取得します。私がutf-8として保存すれば、それは動作します。

+0

ソースをUTF-8として保存すると、OPが取得する内容が取得されます。ソースをiso-8859-1として保存して( 'use utf8;'を削除すると)、同じメッセージに加えて、「エラー:文字列はUTF-8ではありません」というメッセージが表示されます。 – ikegami

関連する問題