TOP>>OBAQ>>HTMLジェネレーター 概略ツアー<OBAQ>構成定義アプリケーションサーバリファレンスサイトマップ

HTMLツリーの操作


HTMLツリーの生成

HTMLファイルをパースしないで、プログラム内でHTMLツリーを直接生成することもできます。

e = Element.new(:a, Attr.new(:href, "http:://www.ruby-lang.org/")) { "ruby" }
puts e.to_s # => <a href="http:://www.ruby-lang.org/">ruby</a>

これは繁雑なので、以下のような略記法も用意してあります。

e = E(:a, A(:href, "http:://www.ruby-lang.org/")) { "ruby" }
puts e.to_s # => <a href="http:://www.ruby-lang.org/">ruby</a>

あるHTMLをプログラムで生成する時に、 どのような記述をしたらよいかは以下のようにして調べることができます。

template = HtmlParser.parse_inline '<a href="http:://www.ruby-lang.org/">ruby</a>'
puts template.to_ruby # => E(:a, A(:href, "http:://www.ruby-lang.org/")) { "ruby" }

つまり、ObaqのHTMLツリーは、自分を表現するRubyスクリプトを出力するto_rubyというメソッドを持っています。 このメソッドを呼び出すことで、任意のHTMLをRubyスクリプトにすることが可能です。

なお、この処理を行なうコマンド obaq2htmlも用意してあります。

$ html2obaq htmlファイル名

で、指定したhtmlファイルと同等のhtmlを出力するrubyスクリプトを出力します。

$ html2obaq htmlファイル名 | ruby

で実際に、そのHTMLが出力され

$ html2obaq htmlファイル名 | ruby | w3m -T text/html

でそれを表示して確認することができます。

HTMLツリーの検索

HTMLツリーには、子要素を検索するメソッドもあります。 次のツリーを例にして説明します。

tree = HtmlParser.parse_inline <<-END
<html>
  <body>
  <h1 id=title></h1>
  <table id=table1 border=1>
    <tr id=header><th>col1</th><th>col2</th></tr>
    <tr id=line1 bgcolor="#ff99ff"> <td id=col11><td id=col12></tr>
    <tr id=line2 bgcolor="#66ffff"><td id=col21><td id=col22></tr>
  </table>
  </body>
</html>
END

タグによる検索

検索のメソッドは、findです。 findはブロック引数を取り、そのブロックが真を返した場合に、 その要素を返却します。 ブロックにはトラバースしているツリーの要素が順番に渡されます。

body = tree.find  { |e| e.tagname == "h1" }
puts body.to_s  # => <h1 id="title"></h1>

この例では、tagnameが"h1"である要素を検索しています。

属性による検索

Treeの要素(Htmlgen::Element)は、[]による属性の取り出しをサポートしています。

line1 = tree.find { |e| e[:id] == "line1" }
puts line1.to_s
# => <tr id=line1 bgcolor="#ff99ff"> <td id=col11><td id=col12></tr>

この例では、id="line1" という属性を持つ要素を検索しています。

Htmlツリーの操作

Htmlgen::Elementは実際には、eachによって子要素をトラバースするEnumerableオブジェクトです。 従って、Enumerableに含まれるメソッドは全部使用できます。

a = tree.find_all do |e| 
  e.tagname == "tr" 
end.collect do |e|
  e[:id]
end
p a # => ["header", "line1", "line2"]

Treeを修正することも可能です。

tree.each do |e|
  case e[:id]
  when  "title"
     e.set_text("TITLE TEXT")
  when "table1"
     e[:border] = 0
  end
end
puts tree.to_s

この結果は次のようになります。

<html>
  <body>
  <h1 id="title">TITLE TEXT</h1>
  <table id="table1" border="0">
  ....以下省略  

ページトップへ