XMLファイルを使う必要にかられて、ちょっと調べてみました。
実際のプログラムを作る際には、XPashやCSSでの検索に対応したGem1のオブジェクトを使った方がいいとは思いますが、それでも軽く中身を確認するためにはHashで取り込めると便利なので。
具体的には、ActiveSupportを使った方法とXmlSimpleというgemを使った方法が見つかったので、それらの比較になります。
インストール方法
$ gem install activesupport
$ gem install xml-simple
gemなので、特筆することはなく。
使い方
require 'active_support'
require 'active_support/core_ext'
hash = Hash.from_xml(open('path/to/file.xml'))
require 'xmlsimple'
hash = XmlSimple.xml_in(open("path/to/file.xml"))
使い方もほぼ同じですね。
なお、今回の例ではそれぞれの引数にopen
メソッドで開いたFileオブジェクトを渡していますが、XMLのデータ自体を文字列で渡すことも出来るようです。
出力結果
以下のXMLデータを読み込ませた結果で比較します。
<package>
<track is_inst="true">
<track_no>1</track_no>
<title>タイトル1</title>
</track>
<track>
<track_no>2</track_no>
<title code="12345">タイトル2</title>
<single />
</track>
</package>
{
"package" => {
"track" => [
[0] {
"is_inst" => "true",
"track_no" => "1",
"title" => "タイトル1"
},
[1] {
"track_no" => "2",
"title" => "タイトル2",
"single" => nil
}
]
}
}
{
"track" => [
[0] {
"is_inst" => "true",
"track_no" => [
[0] "1"
],
"title" => [
[0] "タイトル1"
]
},
[1] {
"track_no" => [
[0] "2"
],
"title" => [
[0] {
"code" => "12345",
"content" => "タイトル2"
}
],
"single" => [
[0] {}
]
}
]
}
ActiveSupportは、code
というattributeが欠損してますね(is_inst
は残っていますが、その差の違いは不明です・・・)。なので、attributeが重要なシーンでは使えなさそうです。
逆に、XmlSimpleはすべてのデータが反映されていますが、attributeはString型、elementはArray型で格納されるようです。確かにわかりやすいですが、elementしか使わない場合などに一気にeach句で回したりするのには不便ですね・・・
結論: 適材適所。
処理時間
最後に処理時間を計測しました。
- 実行コマンド
- 使い方の部分のコマンドをそのまま。
- 対象データ
- 少し大きめの某XMLファイル(5.2MB/144747行)
- 計測方法
- 計測マシンは、自分のMacbookPro(Core i7 3GHz/16GB)
- rubyのバージョン
2.2.0p0
- ruby標準のbenchmarkライブラリを使いました。
user system total real
9.870000 0.170000 10.040000 ( 10.047934)
user system total real
10.600000 0.180000 10.780000 ( 10.855242)
結論: 性能は考慮材料にならなさそう。
注意点
どこに書いたらいいのかわからなかったので、ハマった点を最後に書いておきます。
rubyのopenメソッドでは文字コードを指定してファイルを開く事が可能ですが、今回の両gemはそれよりもXMLデータ内のXML宣言(<?xml version="1.0" encoding="Shift_Jis"?>
みたいなの)の方が優先されるようです。
そのため、ShiftJISのデータをパースしようとすると、文字化けが起きるばかりではなく、いわゆるダメ文字のせいで失敗する事さえあります。
これを回避するためには、XMLデータ内のXML宣言を消した上で処理するしかなさそうです。やっぱり、この方法で本番利用するのは現実味がないです。