パースするだけがNokogiriじゃない。
ちょっとしたhtmlを生成するのに、ERBみたいなテンプレートエンジン使うのも面倒だ。
そんなときにNokogiriを使うといい感じに書けます。
とはいえいつも使い方を忘れるのでメモ。
例
NokogiriでHTMLを生成するスクリプト
require 'nokogiri'
l = %w(foo bar baz)
root = Nokogiri::HTML::DocumentFragment.parse("")
Nokogiri::HTML::Builder.with(root) do |doc|
doc.div.nav.index do
doc.h1 "LIST"
doc.ul do
l.each.with_index do |x, i|
doc.li x, class: "item-list", id: i
end
end
doc.br # これだと<br>になる
doc << "<br />" # ノードを挿入する場合
doc.text "<br />\n" # テキストノードとして挿入する場合(自動的にエスケープされる)
end
end
puts root.to_html
生成されたHTML
<div class="nav index">
<h1>LIST</h1>
<ul>
<li class="item-list" id="0">foo</li>
<li class="item-list" id="1">bar</li>
<li class="item-list" id="2">baz</li>
</ul>
<br><br><br />
</div>
覚書
- doc.タグ名[.クラス名. ...]([テキスト][, 属性]){ 入れ子 }
- タグ名をメソッドとして呼び出す。入れ子はブロックの中で記述する。
- 動的にタグ名を変える場合はsendとか使う。
- 属性は {attr: value[, ...]} の形。
- classはメソッドチェインでの指定も可能(複数OK)
- テキストノードはメソッドの第1引数に渡すか、 doc.text で追加する。
- 既に作ってあるノードを挿入する場合は doc<<
- 閉じタグ付きの改行
<br />
を挿入しても閉じタグ外れるらしい。
おまけ:ヒアドキュメントでなんとかした例
Rubyのヒアドキュメントは便利なのではじめはこうやろうとしました。
l = %w(foo bar baz)
html = <<HTML1 + l.map.with_index{|x,i| <<HTML2 % [i, x]}.join + <<HTML3
<div class="nav index">
<h1>LIST</h1>
<ul>
HTML1
<li class="item-list" id="%s">%s</li>
HTML2
</ul>
</div>
HTML3
puts html
<div class="nav index">
<h1>LIST</h1>
<ul>
<li class="item-list" id="0">foo</li>
<li class="item-list" id="1">bar</li>
<li class="item-list" id="2">baz</li>
</ul>
</div>
このあと滅茶苦茶ノコギリした。