株式会社クリアコード > ククログ

ククログ

クリアコードはプログラミングが好きなソフトウェア開発者を2名募集しています。

クリアコードはフリーソフトウェア開発で培った技術力を提供しています。特にMozilla製品(Mozilla FirefoxとMozilla Thunderbird)Rubyに関連した開発を得意としています。

Ohloh profile for kou RubyKaigi2010 Sponsor RubyKaigi2010 Speaker RubyKaigi2010 Committer
«2009年5月のmilter manager 最新 groongaでN-gramを使って全文検索»
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|
タグ:

Ruby 1.9.1とREXMLとXML宣言のエンコーディング

Ruby 1.9.1付属のREXMLではXML宣言のエンコーディングの扱いに問題があるためvalidなXMLでもパースできない場合があるという話です。

問題

Ruby 1.9では文字列や正規表現がエンコーディング情報を持つため、REXMLのように正規表現ベースでXMLをパースしている場合は、エンコーディングを適切に設定しないとパースに失敗することがあります。

例えば、tDiaryのseach-yahoo.rbプラグインがこの問題に遭遇しています。

原因

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だけ見てもエンコーディングミスマッチがどこで起こっているかはわかりません。問題が発生したときは問題解決につながるエラーメッセージを提供したいものですね。

Tags: Ruby | このエントリの Delicious history 5 users | このエントリを含む Yahoo!ブックマーク | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | このエントリを含む FC2ブックマーク | このエントリを含む Buzzurl | このエントリをTweetする | | Permalink
2009-05-11

«2009年5月のmilter manager 最新 groongaでN-gramを使って全文検索»
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|