REXML で大きな XML ファイルを処理したらあまりにも遅かった。Ruby で書かれているのでいたし方ないんですが。もちろん REXML は標準でついているし、手軽に使えて良いという大きなメリットがあるけど、行う処理が数時間レベルなので速くしたい。そこで Libxml http://libxml.rubyforge.org/ を試すことに。 行うのは XML → XML 変換なので、エンティティの出力が気になった。そこで次のようなコードを実行して、結果を比較してみる。
テストしたコード 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 require 'rubygems' require 'xml/libxml' require 'rexml/document' str =<<EOS <?xml version="1.0" encoding="UTF-8" ?> <root> <title>Tosshi's メモ書き</title> <array> <item attr='''> <html> 'TAG" </item > <item attr=""" ><!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]></item> </array> </root> EOS puts <<EOS \[ libxml-ruby \] EOS xp = XML::Parser.new xp.string = str libxmldoc = xp.parse puts " document :" puts libxmldoc node = libxmldoc.root.find_first(" title") print " Node :" puts node print " content :" puts node.content print " child .to_s: " puts node.child.to_s libxmldoc.root.find(" array/item").each do |item| print " Node :" puts item print " content :" puts item.content print " child .to_s: " puts item.child.to_s end puts <<EOS \[ REXML \] EOS rexmldoc = REXML::Document.new(str) puts " Document :" puts rexmldoc el = rexmldoc.root.elements\[" title"\] print " Element :" puts el print " text :" puts el.text print " get_text :" puts el.get_text rexmldoc.root.elements.each(" array/item") do |item| print " Element :" puts item print " text :" puts item.text print " get_text :" puts item.get_text end
結果
libxml はアポストロフィとダブルクォートを必要なときだけ実体名にエスケープする。
REXML は属性値は固定でアポストロフィで囲い、アポストロフィとダブルクォートは必ず実体名にエスケープする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 $ ruby testxml.rb \[ libxml-ruby \] Document : <?xml version="1.0" encoding="UTF-8"?> <root> <title>Tosshi's メモ書き</title> <array> <item attr="'"> <html> 'TAG" </item> <item attr="""><!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]></item> </array> </root> Node :<title>Tosshi's メモ書き</title> content :Tosshi's メモ書き child.to_s:Tosshi's メモ書き Node :<item attr="'"> <html> 'TAG" </item> content : <html> 'TAG" child.to_s: <html> 'TAG" Node :<item attr="""><!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]></item> content : CDATA <html> 'TAG&qout; <>"' child.to_s:<!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]> \[ REXML \] Document : <?xml version='1.0' encoding='UTF-8'?> <root> <title>Tosshi's メモ書き</title> <array> <item attr='''> <html> 'TAG" </item> <item attr='"'><!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]></item> </array> </root> Element :<title>Tosshi's メモ書き</title> text :Tosshi's メモ書き get_text :Tosshi's メモ書き Element :<item attr='''> <html> 'TAG" </item> text : <html> 'TAG" get_text : <html> 'TAG" Element :<item attr='"'><!\[CDATA\[ CDATA <html> 'TAG&qout; <>"' \]\]></item> text : CDATA <html> 'TAG&qout; <>"' get_text : CDATA <html> 'TAG&qout; <>"'
tilfin
freelance software engineer