HTML::Element

HTML::TreeBuilderオブジェクトのノードを意味するオブジェクト。ノード間の繋がりをたどってHTMLのツリー構造を検索するメソッドなどが実装されている。

HTML::TreeBuilderはこのクラスを継承しているので、HTML::TreeBuilderオブジェクトを生成してこのクラスのメソッドを使ってHTMLの解析な どを実行する。

HTML::Elementを単独で使ってツリー構造を生成し、最後にas_HTMLメソッドでHTMLを生成する事も可能であるが、これらの生成用メソッドに関しては一切説明していないので、CPANを参照のこと。

注意事項

as_text , as_HTML メソッドには、一部難がある。
これらのメソッドは、  を0xA0 という1バイトのコードに変換して出力する。U+A0は、unicodeで  と同じ”改行を伴わないスペース”という意味なのだが、このコードをutf-8表現にするでもなく、生のunicodeのまま(つまり、0xA0出力してしまう。(ブラウザによるが) このコードは正しく表示されない。恐らく、元普通のスペース(0x20)だったものと、 だったものを区別するために内部的にU+A0を使用していると思われるが、出力する際に正しいコードに戻してくれない。

対処方法1:utf-8またはシフトJIS以外の場合
as_text, as_HTMLに出力させた後、出力文字列の\xA0をスペース、または、 に置換する。

対処方法2:utf-8またはシフトJISの場合
ワイドキャラクタの2バイト目(以降)に0xA0を含むので、単純に置換ができない。
元HTMLの を(例えば)$nbsp; に置換した後にHTML::TreeBuilderなどに入力しておき、as_text, as_HTMLに出力させた後、$nbsp; をスペース、または、  に置換する。

基本メソッド

my $value = $tree->attr($attr);
ノードのタグの属性値を返す。指定された属性を持たない場合は、undefを返す。

my $name = $tree->tag();
ノードのタグ名を返す。タグ名は、常に小文字に変換される。

my $parent = $tree->parent();
親ノードを返す。ルートノードであればundefを返す。

my @childs = $tree->content_list();
子ノードのリストを返す。子ノードは、HTML::Elementオブジェクト、または、このタグ直下のテキスト(文字列)。子ノードがない場合は空配列 を返す。

my $childs = $tree->content();
子ノードのリストへの参照を返す。子ノードは、HTML::Elementオブジェクト、または、このタグ直下のテキスト(文字列)。子ノードがない場合 はundefを返す。

my $childs = $tree->content_array_ref();
子ノードのリストへの参照を返す。子ノードは、HTML::Elementオブジェクト、または、このタグ直下のテキスト(文字列)。子ノードがない場合 は空配列への参照を返す。

my @childs = $tree-> content_refs_list();
子ノードへの参照リスト(各子ノードへの参照を要素にした配列)を返す。子ノードは、HTML::Elementオブジェクト、または、このタグ直下のテ キスト(文字列)。ノードがない場合は、空配列を返す。

my %attrs = $tree->all_attr();
ノードの全ての属性をハッシュ形式で返す。属性には、HTML::Elementが内部的に生成した属性が含まれる(_parent,_content,_tagなど)。

my @names = $tree->all_attr_names();
ノードの全ての属性名リストを返す。属性には、HTML::Elementが内部的に生成した属性が含まれる(_parent,_content,_tagなど)。

my %attrs = $tree->all_external_attr();
ノードのHTML属性をハッシュ形式で返す。HTML::Elementが内部的に生成した属性が含まれない。

my @names = $tree->all_external_attr_names();
ノードのHTML属性名リストを返す。HTML::Elementが内部的に生成した属性が含まれない。

表示系メソッド

$tree->dump();  または  $tree->dump(*FH);
ノード配下のツリー構造を下記の形式でSTDOUTまたはファイルハンドルにダンプ出力する。
<開始タグ> @アドレス
   "タグ内のテキスト"(コンテンツ)
   <子ノードの開始タグ> @アドレス
       :
アドレスは、@0.x.y の様な形式。
$tree->address('0.x.y'); で @0.x.yのノードのHTML::Elementオブジェクトを得られる。

my $html = $tree->as_HTML([$unsafe_chars [,$indent_char]]);
ノード配下のオブジェクトをHTMLに再構成して返す。
$unsafe_charsを指定すると、指定した文字のみHTMLエンコードする。デフォルトは、qq/<>&'"/ と0x80以上の文字がエンコードされる。日本語の場合は、U+A0を除く0x80以上の文字をエンコードされると、ブラウザが正しくワイドキャラクタを表示出来なくなるので、必ず、qq/<>&'"/ を指定する必要がある。
$ident_charを指定すると、指定した文字でインデントしたツリー構造を出力する。"\t" や " "を指定する。デフォルトはインデントなし(改行もせずにベタ文字列が出力される)。もっとも、開始タグの出力位置をインデントするだけで、終了タグの扱いがうまくないので、さして見やすくはならない。

my $text = $tree->as_text();
ノード配下のタグ内の全てのテキストを連結した文字列を返す。テキスト内の改行コードと連続した空白は、空白1個に置き換えられる。元のHTML の構造によるが、前後に余分な空白が含まれる場合があるので、空白が意味を持つ場合を除いてas_trimmed_textの方がお勧め。
タグ構造は全く考慮されない。つまり、<br>タグは独立したテキストなしのノードとして扱われるので改行情報は失われ、<p></p>などの段落情報も失われたベタ文字列が返される。改行や段落を考慮したテキストを復元したい場合は、ツリー構造を追跡して改行などを補いながら文字列を再構成するしかない。

my $text = $tree->as_trimmed_text();
ノード配下のタグ内の全てのテキストを前後の余分な空白を取り除いて連結した文字列を返す。テキスト内の改行コードと連続した空白は、空白1個に置き換えられる。タグ構造が考慮されない事は、as_textと同じ。

my $tag = $tree->starttag();
ノードの開始タグを再構成して返す(タグ名ではなく、<tag attr="value"...>形式のタグ)。

my $tag = $tree->endtag();
ノードの終了タグを再構成して返す。

検索系メソッド

$tree->is_inside($tag, ...); または $tree->is_inside($element, ...);
$tagはタグ名、$elementはHTML::Elementオブジェクト。
ノード配下のノードに$tag、または、$elementが含まれる場合、trueを返す。

$tree->is_empty();
ノードがコンテンツ(テキスト)を持たない時、trueを返す。<image><hr><br>などの他、文字列のない<p></p>タグはtrueになる。

my $index = $tree->pindex();
親ノードのコンテンツリスト(content_list)内での、このノードのインデクス値を返す。ルートノードの場合は、undefが返る。

my @siblings = $tree->left(); または my $sibling = $tree->left();
左側の兄弟ノードリスト、または、すぐ左側の兄弟ノードを返す。兄弟ノードが存在しない場合は、空配列またはundefが返る。

my @siblings = $tree->right(); または my $sibling = $tree->right();
右側の兄弟ノードリスト、または、すぐ右側の兄弟ノードを返す。兄弟ノードが存在しない場合は、空配列またはundefが返る。

my $address = $tree->address();
このノードのルートノードからのアドレス(0.x.y.z形式:dump参照)を返す。

my $element = $tree->address($address);
$addressをアドレスに持つノードを返す。存在しない場合は、undefが返る。
0. から始まるアドレスは、$treeの位置に無関係にルートノードからの絶対アドレスである。$treeからの相対アドレスを指定する場合は、.x.y.z のように$tree以下のアドレスを . で始まる形式で記述する。

my $depth = $tree->depth();
このノードのルートノードからの深さを返す。

my $root = $tree->root();
ルートノードを返す。

my @lineages = $tree->lineage();
このノードの祖先ノードリストを返す。ルートノードの場合は空配列が返る。

my @lineage_tag_names = $tree->lineage_tag_names();
このノードの祖先ノードのタグ名リストを返す。ルートノードの場合は空配列が返る。

my @descendants = $tree->descendants();
このノードの子孫ノードリストを返す。 content_listと異なり、リストにはコンテンツ(ダグ内の文字列)は含まれず、子・孫・...ノードのリストである。

my @elements = $tree->find_by_tag_name($tag); または $tree->find($tag);
$tagはタグ名。
子孫ノードを検索して、タグ名を持つノードのリストを返す。見つからない場合は、undefが返る。

my @elements = $tree->look_down($attr,$value);
$attrは属性名。$valueは属性値。
このノードと子孫ノードを検索して、指定の属性値を持つノードのリストを返す。見つからない場合は、undefが返る。同様の機能のメソッドにfind_by_attributeがあるが、look_downの使用が推奨されている。祖先ノードを検索したい場合は、同様の書式でlook_upメソッドを使う。

my @elements = $tree->look_down($attr,qr/.../);
$attrは属性名。
このノードと子孫ノードを検索して、指定の属性値が正規表現qr/.../にマッチするノードのリストを返す。見つからない場合は、undefが返る。祖先ノードを検索したい場合は、同様の書式でlook_upメソッドを使う。

my @elements = $tree->look_down(\&function);
このノードと各子孫ノードを引数にして&functionを呼び出し、&functionがtrueを返したノードのリストを返す。見つからない場合は、undefが返る。 &functionの引数には、各ノードのHTML::Elenemtオブジェクトが渡されるので、オブジェクトメソッドを使ってノードの内容を調べて true/falseを返す関数にしておく。祖先ノードを検索したい場合は、同様の書式でlook_upメソッドを使う。

my @values = $tree->attr_get_i($attr);
$attrは属性名。
このノードと祖先ノードを検索して、$attr属性値リストを返す。見つからない場合は、undefを返す。子孫ではなく、祖先を検索する点に注意。要するに、祖先から継承される属性に関して、このノードにどの属性値が適用される構造になっているか調べるためのメソッドと思われる。だとすれば、リストで受けずにスカラーで直前の値だけ検索しても十分だろう。

my %map = $tree->tagname_map();
このノードと子孫ノードを検索して、タグ名毎にまとめたノードリストを作成し、タグ名をキー・リストへの参照を値としたハッシュへの参照を返す。

my $links = $tree->extract_links([@wanttags]);
@wanttagsは、検索したいタグ名のリスト。デフォルトは全てのタグ。このノードと子孫ノードを検索して、リンク(a href,img src,など)リストを作成し、リストへの参照を返す。
リストの内容は、下記の形式の配列への参照。
 [0] リンク先のURI
 [1] HTML::Elementオブジェクト
 [2] 属性名(href,srcなど)
 [3] タグ名(a,imgなど)