Kawanet Blog II

アクセスカウンタ

zoom RSS [Perl] Encode::FB_XMLCREFでコード変換に失敗&対策

<<   作成日時 : 2006/05/17 05:47   >>

ブログ気持玉 0 / トラックバック 2 / コメント 0

Perl の Encode モジュールには、FB_XMLCREF というオプションがあり、
変換できない文字を &#xHHHH; 形式で出力してくれて便利です。
(詳しくは Handling Malformed Data を参照)
 
この FB_XMLCREF 出力が好きなので、いつも付けているのですが、
Windows でテストスクリプトが動かないことがあり、よく見ると
FB_XMLCREF の有無がエラーになる原因でした。
FB_XMLCREF を外せば済むのですが、やはり必要なこともあります。
 
以下のサンプルスクリプトで検証してみました。
#!/usr/bin/perl

use strict;
use Encode;

my $utf8 = "\xE6\xBC\xA2\xE5\xAD\x97"; # Kanji in UTF-8
my $sjis = "\x8A\xBF\x8E\x9A"; # Kanji in Shift_JIS

my $test1 = $sjis;
my $test2 = $sjis;
my $test3 = $utf8;
my $test4 = $utf8;
Encode::from_to( $test1, 'Shift_JIS', 'UTF-8' );
Encode::from_to( $test2, 'Shift_JIS', 'UTF-8', Encode::FB_XMLCREF );
Encode::from_to( $test3, 'UTF-8', 'Shift_JIS' );
Encode::from_to( $test4, 'UTF-8', 'Shift_JIS', Encode::FB_XMLCREF );
my $r1 = ($test1 eq $utf8) ? 'UTF-8' : ($test1 eq $sjis) ? 'Shift_JIS' : '?';
my $r2 = ($test2 eq $utf8) ? 'UTF-8' : ($test2 eq $sjis) ? 'Shift_JIS' : '?';
my $r3 = ($test3 eq $utf8) ? 'UTF-8' : ($test3 eq $sjis) ? 'Shift_JIS' : '?';
my $r4 = ($test4 eq $utf8) ? 'UTF-8' : ($test4 eq $sjis) ? 'Shift_JIS' : '?';
my $fb = sprintf( "%04X", Encode::FB_XMLCREF );

print "OS:$^O Perl:$] Encode:$Encode::VERSION FB_XMLCREF:$fb\n";
print "Result:$r1 $r2 $r3 $r4\n";

『漢字』という文字を Shift_JIS〜UTF-8 で相互変換します。
Encode::FB_XMLCREF の有無で計4種類の変換を行います。
手元の環境で実行してみた結果が↓です。

Fedora Core 4
OS:linux Perl:5.008006 Encode:2.08 FB_XMLCREF:0400
Result:UTF-8 UTF-8 Shift_JIS Shift_JIS
Fedora Core 5
OS:linux Perl:5.008008 Encode:2.16 FB_XMLCREF:0408
Result:UTF-8 UTF-8 Shift_JIS Shift_JIS
Mac OS X(OSデフォルト版)
OS:darwin Perl:5.008006 Encode:2.08 FB_XMLCREF:0400
Result:UTF-8 UTF-8 Shift_JIS Shift_JIS
Mac OS X(ソースからインストール版)
OS:darwin Perl:5.008008 Encode:2.12 FB_XMLCREF:0408
Result:UTF-8 Shift_JIS Shift_JIS UTF-8
Windows XP(ActivePerl)
OS:MSWin32 Perl:5.008008 Encode:2.12 FB_XMLCREF:0408
Result:UTF-8 Shift_JIS Shift_JIS UTF-8


前者3件(印)は4種類とも正しい変換結果ですが、
後者2件(印)は FB_XMLCREF が付くと正しく変換できていません。

環境によって、FB_XMLCREF の値が違います。
0408 の場合は、encode.h を見ると ENCODE_LEAVE_SRC が入っています。
しかし FC4/FC5 を見ると、ENCODE_LEAVE_SRC が原因ではなさそうです。

あるいは、Encode.pm バージョン 2.12 特有の問題なのか?
Perl 5.8.8 標準添付のバージョンと思うので、とすると影響が大きい…。
http://search.cpan.org/src/DANKOGAI/Encode-2.17/Changes



(追記:2006/05/21)
FB_XMLCREF が利用できないバージョンが確認できました。
Encode-2.10 で FB_XMLCREF の値が変更(LEAVE_SRC有効)になってから、
Encode-2.13 で解決されるまでが対象でした。2.09 以前も問題なし。
2.10〜2.12 の間も、FB_XMLCREF を使わずに 0x0400 と直打ちすれば
正常に変換されるので、FB_XMLCREF をどのバージョンでも利用したい場合は、
my $check = ( $Encode::VERSION < 2.13 ) ? 0x400 : Encode::FB_XMLCREF();
Encode::from_to( $string, $from, $to, $check );
のようにすれば今後の値変更にも対応できて、良さそうですね。

もちろん、Encode 本体をバージョンアップしてもらうのが最善ですが、
環境によってはなかなかバージョンアップできない場合も多いでしょうから。

CPAN にはない旧バージョンのアーカイブは、弾さんのサイト↓にありました。
http://www.dan.co.jp/~dankogai/cpan/
(ありがとうございます〜!!)



(追記:2006/05/21その2)
0x0400 直打ちじゃなくて、Encode::XMLCREF() が使えるとのこと。
この FB_ の付かない XMLCREF は、POD に詳しい効能などは載っていないなので、
旧バージョンでも使えるのか不安でしたが、確認してみたら Perl 5.8.1 に付属していた
Encode 1.9801 の時代から対応している模様。
0x400 と直打ちするよりも XMLCREF を使ったほうが確かに良いですね。

結論としては、古い環境(OS添付のPerlをそのまま使っていて、Encodeを
最新バージョンに上げられない環境)でも動かしたいプログラム・モジュールで
XMLCREF したい場合は、
my $check = ( $Encode::VERSION < 2.13 ) ? Encode::XMLCREF() : Encode::FB_XMLCREF();
Encode::from_to( $string, $from, $to, $check );
とするか、ベストかな。
あるいは、from_to() を使わずに自前で decode()/encode() するか。(避けたい)

参考に、Perl 各バージョン添付の Encode のバージョンをまとめました。↓
perl-5.8.1 Encode-1.9801 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.2 Encode-1.9801 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.3 Encode-1.99 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.4 Encode-1.99_01 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.5 Encode-2.01 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.6 Encode-2.08 XMLCREF=0x0400 FB_XMLCREF=0x0400
perl-5.8.7 Encode-2.10 XMLCREF=0x0400 FB_XMLCREF=0x0408
perl-5.8.8 Encode-2.12 XMLCREF=0x0400 FB_XMLCREF=0x0408
また、Encode.pm の過去バージョンの参照には↓がオススメとのこと。
http://backpan.cpan.org/modules/by-authors/id/D/DA/DANKOGAI/

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(2件)

タイトル (本文) ブログ名/日時
perl - Encode::from_to() and fallback options
ゆうすけさん、いつも詳細なレビューありがとうございます。 [Perl] Encode::FB_XMLCREFでコード変換に失敗&対策 ゆうすけブログ /ウェブリブログFB_XMLCREF が利用できないバージョンが確認できました。 が、ちょっと事実誤認があるので ...続きを見る
404 Blog Not Found
2006/05/21 12:09
「&#xff5e;」が文字化けする件について苦戦中
エントリーを普通に書くと、おそらくEncodeで変換するときに、「&#xff5e... ...続きを見る
のぶろぐ
2006/11/11 23:37

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
[Perl] Encode::FB_XMLCREFでコード変換に失敗&対策 Kawanet Blog II/BIGLOBEウェブリブログ
文字サイズ:       閉じる