0

XMLファイル「settings.xml」を作成するperlスクリプトを書いています。(XML::Writer を使用)。ファイルを UCS-2 ビッグ エンディアンでエンコードしたいのですが、方法がわかりません。

私は次のようなことを試しましopen(my $output, "> :encoding(UCS-2BE)", "settings.xml");: ANSI としてファイルします。

これを修正する方法、またはファイルを UCS-2 に変換する方法はありますか?

私はPerlの初心者です、これのいくつかが意味をなさない場合は申し訳ありません.

編集:この問題に遭遇した他の人は、以下の回答を参照してください。修正方法の完全な説明が提供されています。

4

2 に答える 2

2

XML::Writer は、US-ASCII と UTF-8 以外はサポートしていません (ENCODINGコンストラクタ引数のドキュメントに記載されています)。XML::Writer を使用して UCS-2be XML ドキュメントを作成するのは難しいですが、不可能ではありません。

use XML::Writer qw( );

# XML::Writer doesn't encode for you, so we need to use :encoding.
# The :raw avoids a problem with CRLF conversion on Windows.
open(my $fh, '>:raw:encoding(UCS-2be)', $qfn)
   or die("Can't create \"$qfn\": $!\n");

# This prints the BOM. It's optional, but it's useful when using an
# encoding that's not a superset of US-ASCII (such as UCS-2be).
print($fh "\x{FEFF}");

my $writer = XML::Writer->new(
   OUTPUT   => $fh,
   ENCODING => 'US-ASCII',   # Use entities for > U+007F
);
$writer->xmlDecl('UCS-2be');
$writer->startTag('root');
$writer->characters("\x{00041}");
$writer->characters("\x{000C9}");
$writer->characters("\x{10000}");
$writer->endTag();
$writer->end();

欠点: U+007F より上の文字はすべて XML エンティティとして表示されます。上記の例では、

  • U+00041 は " A" ( 00 41) として表示されます。良い。
  • U+000C9 は " É" ( 00 26 00 23 00 78 00 43 00 39 00 3B) として表示されます。最適ではありませんが、大丈夫です。
  • U+10000 は " 𐀀" ( 00 26 00 23 00 78 00 31 00 30 00 30 00 30 00 30 00 3B) として表示されます。U+10000 を で格納するには、XML エンティティが必要ですUCB-2e

U+FFFF を超える文字がライターに提供されないことを保証できる場合にのみ、上記の欠点を回避できます。

use XML::Writer qw( );

# XML::Writer doesn't encode for you, so we need to use :encoding.
# The :raw avoids a problem with CRLF conversion on Windows.
open(my $fh, '>:raw:encoding(UCS-2be)', $qfn)
   or die("Can't create \"$qfn\": $!\n");

# This prints the BOM. It's optional, but it's useful when using an
# encoding that's not a superset of US-ASCII (such as UCS-2be).
print($fh "\x{FEFF}");

my $writer = XML::Writer->new(
   OUTPUT   => $fh,
   ENCODING => 'UTF-8',   # Don't use entities.
);
$writer->xmlDecl('UCS-2be');
$writer->startTag('root');
$writer->characters("\x{00041}");
$writer->characters("\x{000C9}");
#$writer->characters("\x{10000}");  # This causes a fatal error
$writer->endTag();
$writer->end();
  • U+00041 は " A" ( 00 41) として表示されます。良い。
  • U+000C9 は " É" ( 00 C9) として表示されます。良い。
  • U+10000 は致命的なエラーを引き起こします。

そして、マイナス面なしでそれを行う方法は次のとおりです。

use Encode      qw( decode encode );
use XML::Writer qw( );

my $xml;
{
   # XML::Writer doesn't encode for you, so we need to use :encoding.
   open(my $fh, '>:encoding(UTF-8)', \$xml);

   # This prints the BOM. It's optional, but it's useful when using an
   # encoding that's not a superset of US-ASCII (such as UCS-2be).
   print($fh "\x{FEFF}");

   my $writer = XML::Writer->new(
      OUTPUT   => $fh,
      ENCODING => 'UTF-8',   # Don't use entities.
   );
   $writer->xmlDecl('UCS-2be');
   $writer->startTag('root');
   $writer->characters("\x{00041}");
   $writer->characters("\x{000C9}");
   $writer->characters("\x{10000}");
   $writer->endTag();
   $writer->end();
   close($fh);
}

# Fix encoding.
$xml = decode('UTF-8', $xml);
$xml =~ s/([^\x{0000}-\x{FFFF}])/ sprintf('&#x%X;', ord($1)) /eg;
$xml = encode('UCS-2be', $xml);

open(my $fh, '>:raw', $qfn)
   or die("Can't create \"$qfn\": $!\n");

print($fh $xml);
  • U+00041 は " A" ( 00 41) として表示されます。良い。
  • U+000C9 は " É" ( 00 C9) として表示されます。良い。
  • U+10000 は " 𐀀" ( 00 26 00 23 00 78 00 31 00 30 00 30 00 30 00 30 00 3B) として表示されます。U+10000 を で格納するには、XML エンティティが必要ですUCB-2e
于 2013-05-23T19:45:32.187 に答える
1

何がうまくいかなかったのかは説明していませんが、一部の perl バージョンが Windows でエンコーディングと crlf レイヤーの間の相互作用が悪いというバグに遭遇している可能性があります。もしそうなら、これはうまくいくはずです:

open(my $output, "> :raw:perlio:encoding(UCS-2BE):crlf:utf8", "settings.xml");

(説明については、 http://www.perlmonks.org/?node_id=608532を参照してください。)

そうでない場合は、「ファイル出力をめちゃくちゃにするだけ」以上の情報を提供してください。問題を示す短いスクリプトが役立ちます。

于 2013-05-23T18:54:25.377 に答える