NAME
TL::HtmlFilter - HTMLのパースと書き換え
SYNOPSIS
my $filter = $TL->newHtmlFilter(
interest => ['form', 'textarea'],
);
$filter->set($html);
while (my ($context, $elem) = $filter->next) {
...
}
print $filter->toStr;
DESCRIPTION
METHODS
TL::HtmlFilter
- new
-
$TL->newHtmlFilter(%options)
フィルタオブジェクトを作る。オプションは以下の通り:
- interest
-
要素名、もしくは要素名にマッチする正規表現を要素とする配列。 正規表現の場合は
qr//
でコンパイルしなければならない。 マッチしなかった要素はスキップされる。省略可能。注意: 要素が文字列の場合は大文字小文字を無視した比較がされるが、 正規表現で同じ動作をさせるには qr/h\d/i のように i フラグを 付けなければならない。
- track
-
要素名、もしくは要素名にマッチする正規表現を要素とする配列。 正規表現の場合は
qr//
でコンパイルしなければならない。 マッチした要素は、その子要素内で取り出す事が出来る。省略可能。注意: 要素が文字列の場合は大文字小文字を無視した比較がされるが、 正規表現で同じ動作をさせるには qr/h\d/i のように i フラグを 付けなければならない。
- filter_text
-
真なら要素内のテキスト部分も検出する。
- filter_comment
-
真ならコメントも検出する。
- my_bootstrap
-
内部メソッド
- set
-
$filter->set($html)
パース対象のHTMLを設定する。
- toStr
-
my $html = $filter->toStr()
フィルタリング結果のHTMLを文字列で返す。
- next
-
my ($context, $elem) = $filter->next;
次の要素/テキスト/コメントを取り出す。 戻り値は二つで、最初の項目は "TL::HtmlFilter::Context" 、 次の項目は "TL::HtmlFilter::ElementBase" のオブジェクトである。
TL::HtmlFilter::Context
- newElement
-
$context->newElement($name)
指定された要素名を持つ "TL::HtmlFilter::Element" を作成して返す。
- newText
-
$context->newText($str)
指定された内容を持つ "TL::HtmlFilter::Text" を作成して返す。
- newComment
-
$context->newComment($str)
指定された内容を持つ "TL::HtmlFilter::Comment" を作成して返す。
- in
-
my $element = $context->in($name)
現在の文脈が、指定された名前を持つ要素の中であれば、その要素を返す。 要素の中であるとは、現在の要素がその要素の子孫であるか、その要素内に 含まれるテキストやコメントである場合を云う。
- add
-
$context->add($elem) $context->add('text')
新たな要素を、現在の要素の直後に挿入する。 引数は文字列または "TL::HtmlFilter::ElementBase" でなければならない。
$context->add('text')
は$context->add($context->newText('text'))
と同値である。 - delete
-
現在の要素を削除する。
TL::HtmlFilter::ElementBase
このクラスは以下のクラスの親クラスである。
- isElement
-
$elem->isElement()
"TL::HtmlFilter::Element" のインスタンスであれば1を返す。
- isText
-
"TL::HtmlFilter::Text" のインスタンスであれば1を返す。
- isComment
-
"TL::HtmlFilter::Comment" のインスタンスであれば1を返す。
TL::HtmlFilter::Element
- name
-
$elem->name() $elem->name($new_name)
要素名を返す。引数が与えられた場合は要素名を変更する。 元の要素名が大文字であった場合には、この関数も大文字で返す事に注意。
- parse
-
$elem->parse('<foo bar="111" baz="222">')
文字列で渡されたHTML要素をパースして、要素名と属性を置き換える。
- attr
-
$elem->attr($key) $elem->attr($key => $value)
指定された属性名を持つ属性があれば、その値を返す。 引数が二つ指定された場合は、指定された属性値を書換える。 属性名の大文字小文字は保存されるが、検索時には区別されない。
- attrList
-
my @attrs = $elem->attrList()
存在する全ての属性名を配列で返す。
- end
-
$elem->end() $elem->end('checked')
属性値の存在しない属性名があれば返す。値が指定された場合は、その値を設定する。 input要素の"checked"等、またXHTMLの空要素 "/" が該当する。
- tail
-
end の別名。
- toStr
-
$str = $elem->toStr
要素を文字列化する。この要素が文字列をパースして作られたものである時は、 パースした文字列の属性の順序が保存される。
TL::HtmlFilter::Text
- str
-
$elem->str() $elem->str($string)
テキストの内容を返す。値が指定された場合は、内容を置き換える。
- toStr
-
テキストの内容を返す。
TL::HtmlFilter::Comment
- str
-
$elem->str() $elem->str($string)
コメントの内容を返す。"<!-- -->"は付かない。 値が指定された場合は内容を置き換える。文字列が"--"を含んでいてはならない。
- toStr
-
"<!-- -->"を付けた内容を返す。
サンプル
コード
# フィルタの準備
my $filt = $TL->newHtmlFilter(
# a, form, b要素のみ検出する。bは閉じタグも見る。それ以外は見ない。
interest => [qw(^a$ form /?b)], # 正規表現の配列
# select, option要素の場合は、その要素内で$context->in('select')を呼ぶ事で
# TL::HtmlFilter::Elementのオブジェクトを得る事が出来る。
track => [qw(select option)], # 正規表現の配列
# 真ならタグ以外の部分も見る。コメントは別扱い。
filter_text => 1,
# 真ならコメントの部分も見る。
filter_comment => 1,
);
# フィルタに通すHTMLを設定
$filt->set(q{
<form>
<select>
<a href="http://example.com/" target="_new">foo</a>
<b>bold</b>
<option></option>
</select>
<!-- this is a comment -->
</form>});
while (my ($context, $elem) = $filt->next) {
if ($elem->isElement) {
if ($elem->name eq 'a') {
# <select>要素の中なら、href属性を書換える
if ($context->in('select')) {
$elem->attr(href => 'http://ymir.jp/');
}
}
elsif ($elem->name eq 'form') {
# form要素の開始直後に別の要素を挿入
my $hidden = $context->newElement('input');
$hidden->attr(name => 'foo');
$hidden->attr(type => 'hidden');
$hidden->end('/'); # <input name="foo" type="hidden" />を作る
$context->add($hidden);
}
elsif ($elem->name eq 'b' or $elem->name eq '/b') {
# b要素は消す。
$context->delete;
}
}
elsif ($elem->isText) {
if ($context->in('option')) {
# <option>の中なら書換える
$context->delete;
$context->add('AAAAA'); # テキストを追加。
# $context->add($context->newText('AAAAA')); と等価。
# 同時にこのテキストの親であるoption要素に属性を追加する。
$context->in('option')->attr(foo => 'bar');
}
}
elsif ($elem->isComment) {
# コメントは全て消す。
$context->delete;
}
}
# フィルタリング結果を出力する
print $filt->toStr, "\n";
実行結果
<form><input name="foo" type="hidden" />
<select>
<a href="http://ymir.jp/" target="_new">foo</a>
bold
<option foo="bar">AAAAA</option>
</select>
</form>