HTML::TreeBuilder でパースして木を作って元に戻すと,元通りにならない。p の終了タグが消えてしまう。調べてみると,これはバグではなく,設定が不十分なのが原因だった。
HTML::TreeBuilder は,HTML 文書を構文解析して木を作ってくれる Perl モジュールである (HTML::TreeBuilder)。木の変更,追加,削除も可能で,処理後に HTML 形式で出力することができる,とても強力なツールである。
HTML::TreeBuilder を使って MT のプラグインを書いてみたところ,作った木が元に戻らないことが発覚。捨ててしまおうかと思ったが,マニュアルをよく読むと答が書いてあった。濡れ衣着せて悪いことしたな,TreeBuilder。
環境は,Perl 5.8.6, HTML::TreeBuilder 3.23, HTML::Element 3.23, HTML::Parser 3.56, HTML::Tagset 3.20 である。
まず,HTML::Element の例にある HTML に p 要素を追加し,構文解析してから元に戻してみる。プログラムは次の通り。
HTML::Element ドキュメントの例題の HTML に「<p>I like potatoes and tomatoes!</p>」を追加してある。構文解析は HTML::Parser で行われる (HTML::Parser)。これを実行すると,次の結果となる。
終了タグ </p> が入らずに,</body> が来てしまっている。プログラムでは,閉じ忘れのタグを修正して追加するメソッド「$h->p_strict(1);」を呼んでいるのに,自らが閉じ忘れているではないか。ムカーッとして,捨てそうになったが,心を落ち着けてドキュメントを読んでみると,次の記述があった。
$h->as_HTML($entities, $indent_char, \%optional_end_tags)
If\%optional_end_tags
is specified and defined, it should be a reference to a hash that holds a true value for every tag name whose end tag is optional. Defaults to\%HTML::Element::optionalEndTag
, which is an alias to%HTML::Tagset::optionalEndTag
, which, at time of writing, contains true values forp, li, dt, dd
. A useful value to pass is an empty hashref,{}
, which means that no end-tags are optional for this dump. Otherwise, possibly consider copying%HTML::Tagset::optionalEndTag
to a hash of your own, adding or deleting values as you like, and passing a reference to that hash.HTML::Element - Class for objects that represent HTML elements
as_HTML メソッドでは,「p, li, dt, dd の4つのタグについては,デフォルトでは終了タグを省略する」ということになっているのだ。そして,「これがイヤな人は \%optional_end_tags に {} を指定してね」となっているではないか。そこで,
としたところ,見事終了タグが出力されるようになったのだった。
メデタシメデタシ。なお,終了タグの省略を明示的に指定することもできる。病的ではあるが,次のように
とすると,h1 の終了タグが省略される。このように \%optional_end_tags を指定した場合,デフォルトの p, li, dt, dd の終了タグの指定はなくなる。
「\%optional_end_tags は,ハッシュセット %HTML::Tagset::optionalEndTag と同一のものである」とあるので,このコードを調べてみると,次のようになっていた。
map {} の中にある,最初のセミコロン「;」は何をしているのだろうか? 私の理解の範囲を超えている。
HTML::TreeBuilder で HTML を出力するときは,as_HTML のオプションを最後まで指定すること。
strict な人は特にね。
Master Archive Index
Total Entry Count: 1957