はじめに
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ドキュメントが多くなるとクソほど遅くなるのでおすすめしません。
コメント