EntryFullText もどき
"もどき" にも値しないかもしれないが。寄り道でも、もう少し進んでみた。
extract_after_hook は、ブロックで実装していたけれど、eval に変更した。
ブロックで実装するほうが自然な気がするけれど、今回は気にしない。
形は整ったから Pragger のプラグインに乗せてみるかな。
require 'rubygems' require 'hpricot' def extract_text(text, opt) # argument no check keys = opt[:extract_capture].split(/\s/) if opt.key?(:extract_capture) data = [] text.scan(/#{opt[:extract]}/m) { |r| item = {} if opt.key?(:extract_capture) 1.upto(keys.size) {|i| item[keys[i-1].to_sym] = Regexp.last_match(i) } end if opt.key?(:extract_xpath) doc = Hpricot(r) opt[:extract_xpath].each {|key, val| elem = doc.at(val) if elem.nil? item[key] = '' else item[key] = elem.to_s end } end if opt.key?(:extract_after_hook) eval(opt[:extract_after_hook]) end data << item } data end
- サンプル
というかテストコード
require 'test/unit' require 'extract_text' class Test_extract_text < Test::Unit::TestCase def setup @text =<<EOD <root> <record> <item> <name>user01</name> <id>0</id> <date>2007/11/25</date> <comment>comment01 foobar</comment> </item> <item> <name>user02</name> <id>1</id> <date>2007/11/28</date> <comment>comment02 foobar</comment> </item> <item> <name>user03</name> <id>2</id> <date>2007/11/30</date> <comment>comment03 foobar</comment> </item> </record> </root> EOD end def teardown end def test_extract_after_hook_conf ok_data = [ {:name => "user01", :date => "2007/11/25", :comment => "comment01 foobar", :id => "0"}, {:name => "user02", :date => "2007/11/28", :comment => "comment02 foobar", :id => "1"}, {:name => "user03", :date => "2007/11/30", :comment => "comment03 foobar", :id => "2"} ] data = extract_text(@text, { :extract => %q{<item>.+?</item>}, :extract_xpath => { :name => %q{//name}, :date => %q{//date}, :id => %q{//id}, :comment => %q{//comment}, }, :extract_after_hook => <<-'EOD' item[:name] = item[:name].match(/>(.+?)<\//).to_a[1] item[:date] = item[:date].match(/>(.+?)<\//).to_a[1] item[:id] = item[:id].match(/>(.+?)<\//).to_a[1] item[:comment] = item[:comment].match(/>(.+?)<\//).to_a[1] EOD } ) assert_instance_of(Array, data) assert_equal(3, data.size) 0.upto(data.size - 1) {|i| assert_instance_of(Hash, data[i]) assert_equal(ok_data[i][:name], data[i][:name]) assert_equal(ok_data[i][:date], data[i][:date]) assert_equal(ok_data[i][:comment], data[i][:comment]) assert_equal(ok_data[i][:id], data[i][:id]) } end end