はじめに
RubyのXML処理のする際に、REXMLライブラリのオプションを使うだけでは、空白や改行を削除できませんでした。そこで、Rubyが得意とするメタプログラミングにより、モンキーパッチを作成してメソッドを上書きさせることで実現します
環境
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux]標準のオプションで実施した場合
compress_whitespace オプションをりようすればある程度削除されますが、空白が1つは残ります。
コード
空白文字がわかるように 表示の際に $end を追加してます
require 'rexml/document' def print_doc(doc) doc.get_elements("/xbel").each{|tags| i = 0 tags.get_elements("tag").each{|tag| i+=1 puts "[ tag" + i.to_s + " ]" puts tag.get_text.to_s + "$end" } } end xml_doc=<<'XML' <?xml version="1.0" encoding="UTF-8" ?> <xbel version="1.0"> <tag>aaa</tag> <tag> bbb </tag> <tag> c c c c c </tag> <tag>a a a a a a a a a </tag> <tag> bbb b b b b b </tag> </xbel> XML puts "###############################################" puts "NORMAL" puts "###############################################" doc = REXML::Document.new(xml_doc) print_doc(doc) puts "###############################################" puts "compress_whitespace" puts "###############################################" doc1 = REXML::Document.new(xml_doc,{:compress_whitespace => :all})
実行結果
############################################### NORMAL ############################################### [ tag1 ] aaa$end [ tag2 ] bbb $end [ tag3 ] c c c c c $end [ tag4 ] a a a a a a a a a $end [ tag5 ] bbb b b b b b $end
############################################### compress_whitespace ############################################### [ tag1 ] aaa$end [ tag2 ] bbb $end [ tag3 ] c c c c c $end [ tag4 ] a a a a a a a a a $end [ tag5 ] bbb b b b b b $end
モンキーパッチによる実装をした場合
REXML::Element クラスに対するモンキーパッチを作成して既存のメソッドを上書きしてますコード
require 'rexml/document' def print_doc(doc) doc.get_elements("/xbel").each{|tags| i = 0 tags.get_elements("tag").each{|tag| i+=1 puts "[ tag" + i.to_s + " ]" puts tag.get_text.to_s + "$end" } } end class REXML::Element alias_method :__get_text__, :get_text def get_text(*path) __get_text__(*path).to_s.gsub(/[ \n]/,"") end private :__get_text__ end xml_doc=<<'XML' <?xml version="1.0" encoding="UTF-8" ?> <xbel version="1.0"> <tag>aaa</tag> <tag> bbb </tag> <tag> c c c c c </tag> <tag>a a a a a a a a a </tag> <tag> bbb b b b b b </tag> </xbel> XML puts "###############################################" puts "Monkey Patch" puts "###############################################" doc = REXML::Document.new(xml_doc) print_doc(doc)
実行結果
############################################### Monkey Patch ############################################### [ tag1 ] aaa$end [ tag2 ] bbb$end [ tag3 ] ccccc$end [ tag4 ] aaaaaaaaa$end [ tag5 ] bbbbbbbb$end
うまくいきました。
ちなみにXMLドキュメントそのものに対して、正規表現で置換処理をさせることも可能ですが、
XMLドキュメントが多くなるとクソほど遅くなるのでおすすめしません。
コメント