使用哈希键使用 XML::LibXML 编写 xml 文件时出现编码错误

sid*_*com 5 xml unicode perl hash encoding

这个问题与这个问题有关:Hash keys encoding: Why I get here with Devel::Peek::Dump two different results?
当我取消注释该# utf8::upgrade( $name );行或注释掉该$hash{'müller'} = 'magenta';行时,它会起作用。

#!/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 );
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 3

根据 XML::LibXML,\'m\xc3\xbcller\' eq \'m\xc3\xbcller\'true 或 false 取决于字符串的内部存储方式。那是一个错误。具体来说,为 UTF8 标志指定含义被称为“Unicode Bug”,并且 XML::LibXML 在本页的“编码支持”部分中记录了完全执行此操作的方法。

\n\n

该错误是已知的,但由于向后兼容性原因,无法彻底修复。Perl 提供了两个工具来解决 Unicode Bug 的实例:

\n\n
utf8::upgrade( $sv );    # Switch to the UTF8=1 storage format\nutf8::downgrade( $sv );  # Switch to the UTF8=0 storage format\n
Run Code Online (Sandbox Code Playgroud)\n\n

前者是在这里使用的合适工具。

\n\n
sub _up { my ($s) = @_; utf8::ugprade($s); $s }\n$tag_color->appendTextNode( _up $hash{$name} );\n
Run Code Online (Sandbox Code Playgroud)\n\n

utf8::upgrade注意:即使不这样做也可以使用use utf8;use utf8;仅当您的源代码为 UTF-8 时才使用。

\n