ja ja ja ja ja ja ja ja ja en ja ja ja ja ja ja ja ja ja ja ja en ja zh ja ja zh ja ja ja ja ja zh ja ja ja ja ja en ja en ja ja ja ja ja pl ja ja ja ja ja ja ja ja en ja ja en ja ja vi ja sv eu ja en en hu ja ja en en pl ja ja jbo hbs_lat en ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja
Ruby 1.9.1とREXMLとXML宣言のエンコーディング - 2009-05-11 - ククログ
REXMLは内部でUTF-8を用いています。そのため、パース対象のXMLのエンコーディングをUTF-8に変換しながらパースします。この処理はREXML::SourceまたはREXML::IOSourceで行われます。
しかし、REXML::IOSourceに問題があり、UTF-8に変換しないままパースしてしまう場合があります。これは、入力XMLのエンコーディングがUTF-8に設定されていない、かつ、XML宣言のエンコーディングがUTF-8になっている場合です。ちなみに、REXML::Sourceではこの問題は起きません。
tDiaryのsearch-yahoo.rbでは入力XMLのエンコーディングがASCII-8BITでXML宣言のエンコーディングがUTF-8になっていたため問題に遭遇しました。
search-yahoo.rbではopen-uriを使って入力XMLをHTTP経由で取得しています。open-uriはContent-Typeを見て適切なエンコーディングを設定してくれますが、今回はcharsetが指定されていなかったとのことです。このため、open-uriで取得した入力XMLがASCII-8BITになっていました。
xml = open("http://.../xxx.xml") {|f| f.read} xml.encoding # => ASCII-8BIT document = REXML::Document.new(xml) # => パースエラー
この問題に遭遇してしまった場合は、以下のような解決法があります。
入力XMLのエンコーディングをUTF-8に設定する。
REXML::IOSourceの代わりにREXML::Sourceを使う。
パッチ付きでバグ報告済みなので修正されるのを待つ。
入力XMLのエンコーディングをUTF-8に設定する場合は以下のようになります。
xml = open("http://.../xxx.xml") {|f| f.read} xml.force_encoding("utf-8") document = REXML::Document.new(xml)
REXML::Sourceを使う場合は以下のようになります。
xml = open("http://.../xxx.xml") {|f| f.read} document = REXML::Document.new(REXML::Source.new(xml))
修正されるのを待つ場合は、修正されるまで待ってください。
Ruby 1.9で正規表現ベースのコードがうまく動かない場合はマッチ対象の文字列のエンコーディングを確認しましょう。
ちなみに、REXML::IOSource#matchではエンコーディング関係のエラーを握りつぶしているため、実際に発生するREXML::ParseExceptionだけ見てもエンコーディングミスマッチがどこで起こっているかはわかりません。問題が発生したときは問題解決につながるエラーメッセージを提供したいものですね。
現在クリアコードではソフトウェア開発者を募集しています! フリーソフトウェア開発での開発の仕方をベースに、成果や知識を公開し共有しながら業務に携われます。
2009年5月のmilter manager
groongaでN-gramを使って全文検索
Apache Arrow
milter manager
ククログの記事はCC BY-SA 4.0とGFDLのデュアルライセンスで自由に利用できます。
クリアコードはプログラミングが楽しいソフトウェア開発者を1名募集しています。
クリアコードは「クリアコードをいい感じにする人」を1名募集しています。
クリアコードはフリーソフトウェア開発で培った技術力を提供しています。特にMozilla製品(Mozilla FirefoxとMozilla Thunderbird)とRubyとGroonga(全文検索)に関連した開発を得意としています。