[ruby]REXMLで、XMLファイルのParse失敗した時の対応方法

広告

rubyで、XMLファイルを読み込むために、REXMLを用いて読み込みをするモジュールを作ったのですが、XMLファイルによって以下のようなエラーが出てしまいます。

[実行コード](抜粋)

xml=File.open(filename)
doc = REXML::Document.new(xml)
[実行結果](抜粋)

No close tag for /company/shows/show/cast
Line: 13
Position: 970
Last 80 unconsumed characters:
REXML::ParseException

XMLのタグが正当についておらず、エラーになっている様子。

ちなみに環境は以下のような感じ。

  • OS:OSX(Yosemite)
  • Ruby:2.2.4
  • XMLファイル:ウィンドウズ上のXMLエディタで作成(Windowsのエンコードで保存)

最初は、単純に該当の部分のXMLファイルをエディタで直せば解消するかとも思ったのですが、エディタで開いて見る限りはちゃんとタグは閉じている。
Windowsで作成したファイルの読み込みだったので、エンコーディングの問題を疑ったのですが、それなら全ファイルが引っかかるはずだしと色々ネットで、エンコーディング以外の問題を探ったのですが見当たりませんでした。

■Windowsで作成されたファイルは、文字コードが2つある。

色々、思い悩んだ末、エラーなく取り込めるXMLファイルと取り込めないXMLファイルの文字コードをUNIXのツールNKFで、文字コードを確認してみることにしました。(nkfのmacへのインストールが必要でした)

[取り込みがうまくいくXMLの場合]

$ nkf -g seikou.xml
Shift_JIS

[取り込みがうまくいかないXMLの場合]

$ nkf -g shippai.xml
CP932

同じWindows環境で同じツールで作成したXMLファイルであっても、文字コードが2種類あり、どうやら後者の「CP932」と出るほうがパースがうまくいかない様です。

 

rubyは2.0になって以降はあまりエンコーディングで悩むことがなく、割りと良きに計らって(自動で)外部エンコーディングを判断してくれているようですが、CP932についてはうまくできないようです。File.Openの際の引数指定色々やってみましたが、どうしてもうまく取り込みができません。

■かなり力技で解決しました。

取り込み対象のXMLファイルを全てUTF-8形式に変換することも考えたのですが、Windows上からこれからも更新したり増えたりすることがある上、他のプログラムにも影響を及ぼしそうなので、踏みきれませんでした。

絶対やりかた間違っている気がするのですが、結局以下のように、一旦一時ファイルの形で、ファイルを保存し、そのファイル名を返却するclassを作成しました。

# encoding:UTF-8
# Converter Class
#2015/12/30
#S-JISの形式のファイルをUTF-8に変換して読み込む為のクラス
require 'nkf'
class Converter
 def convert(filename)
  File.open(filename) do |file|
   @contents=NKF.nkf('-w',file.read)
   @contents.gsub!('Shift_JIS','UTF-8')
   @contents.gsub!('shift_jis','UTF-8')
  end
  File.write('data/tempfile.tmp',@contents)
  return 'data/tempfile.tmp'
 end
end

XML内にencodingを指定している所があったため、そちらもUTF-8に書き換えてます。

元のclassでは、ファイルを受け取ったら一度、このクラスをコールして変換後のファイルを受け取って、REXMLでパースする形にしました。
[元のクラスの該当箇所](抜粋)

converted_filename=@converter.convert(@filename)
xml=File.open(converted_filename)
doc = REXML::Document.new(xml)

おかげで、問題なくXMLのがパースできるようになりました。

絶対…間違っている気がする…orz

広告

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です