ちゃんと PREFERRED_PARSER を指定すること。
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
なにかこう、2005年ぐらいにみた感じの話題で恐縮なのですが。
XML::SAX をインストールしたら、いきなり XML::Simple を使ってたコードが
Cannot decode string with wide characters
って言ってコケ始めた。しかし、アプリケーションを再起動してみたらなぜか再現しない。
結論としては、XML::SAX::PurePerl が使われる状態で、XMLin() に utf8 flagged な文字列を渡すと死ぬ。
use XML::Simple; use utf8; $XML::Simple::PREFERRED_PARSER = 'XML::SAX::PurePerl'; $xml = "<xml>あああ</xml>"; XMLin($xml);
再起動したら再現しなかったのは、XML::SAX を入れた後に XML::LibXML もインストールしていて、XML::LibXML が入ると XML::LibXML::SAX が使われる (PurePerl は使われなくなる) から。
ということで、XML::Simple を使う場合は明示的に PREFERRED_PARSER を指定してやって、思わぬ挙動が起きないようにしましょう。
[追記]
そもそも、XML::Simple には bytes を引数として渡すべきなんじゃないか
http://d.hatena.ne.jp/tokuhirom/20090731/1249001060
これはまったく同意です。SAX::PurePerl 以外では flagged なのを渡しても問題なかったので、気がつきませんでした。
自動的に LibXML が使われるのは、
XML::SAX の仕様的には
http://iandeth.dyndns.org/mt/ian/archives/000589.html明示的な指定が無い限り、最後に環境にインストールされたSAXパーサーを利用する
ということのようで、今回の自分の環境のように
の順序でインストールすると、実際に使われるパーサは
- XML::Simple を入れた時点 => XML::Parser
- XML::SAX を入れた時点 => XML::SAX::PurePerl
- XML::LibXML を入れた時点 => XML::LibXML::SAX
と変わっていきます。
こけたアプリケーション (mod_perl 上の web アプリ) は、XML::SAX インストール前までは XML::Parser を使っていて、それが動いたまま XML::SAX を入れたら PurePerl が使われて死んだ。それに気がついて再現しようとコードを書いたときには既に XML::LibXML が入っていて、PurePerl が使われないため再現しない! という時系列。
また、一番最後にインストールされた SAX パーサを使う、という仕様は結構いやらしくて、LibXML を入れた後に force install XML::SAX をすると、XML::SAX::PurePerl がデフォルトに復帰してしまいます。
気がつかないうちに PurePerl が使われて妙に遅くなった、みたいなことを回避するためにも、PREFERRED_PARSER を明示するほうが安全かと。
[追記2]
XML::SAX::PurePerl が flagged で死ぬのは RT にも登録されてました。#19367: parse_string() crashes when handed UTF-8 combining characters