2007年 11月 21日

Hpricot で一部の要素のみ通すフィルタ

require "rubygems"
require "hpricot"

def html_filter(parent, opts, &block)
	block = Proc.new {|x| x} unless block
	def escape(str)
		_escape = { '<'  => '&lt;', '>'  => '&gt;', '"' => '&quot;' }
		str.gsub(/#{_escape.keys.join("|")}/) {|m| _escape[m] }
	end

	ret = ""
	parent.each_child do |c|
		if c.elem?
			empty = Hpricot::ElementContent[c.name] == :EMPTY
			if opts.key?(c.name)
				ret << "<#{c.name}"
				ret << c.attributes.select {|k,v| opts[c.name].include? k}.map {|k,v| %| #{k}="#{escape v}"| }.join
				ret << "#{empty ? " /" : ""}>"
				ret << html_filter(c, opts, &block)
				ret << "</#{c.name}>" unless empty
			else
				ret << "&lt;#{c.name}"
				ret << c.attributes.map {|k,v| %| #{k}="#{escape v}"| }.join
				ret << "#{empty ? " /" : ""}>"
				ret << html_filter(c, opts, &block)
				ret << "&lt;/#{c.name}>" unless empty
			end
		else
			ret << block.call(c.to_s)
		end
	end
	ret
end

doc = Hpricot(inputs)
puts doc
puts html_filter(doc, opts) { |text|
	text.gsub(/¥n/, "<br />¥n")
}

こんなかんじかなぁ。ちょっときもいけど……


関係ないけど Mac でバックスラッシュをコピーして Fx にペーストすると円マークになってこまる。そのままペーストしてるけど、あとからコピペしようとすると使えないんだよね……