@kyanny's blog

My life. Opinions are my own.

HTML::TokeParser の get_token で 'T' (テキスト) 要素についてくる $is_data ってのは何なのか

HTML::TokeParser - Alternative HTML::Parser interface - metacpan.org => HTML::Parser - HTML parser class - metacpan.org ということで、 CDATA セクションの中にあるか、 script とかいくつかのタグの中にあるテキストデータの場合だけ $token->[2] の $is_data に 1 が入るということらしい。

$p->get_token

    This method will return the next token found in the HTML document, or undef at the end of the document. The token is returned as an array reference. The first element of the array will be a string denoting the type of this token: "S" for start tag, "E" for end tag, "T" for text, "C" for comment, "D" for declaration, and "PI" for process instructions. The rest of the token array depend on the type like this:

      ["S",  $tag, $attr, $attrseq, $text]
      ["E",  $tag, $text]
      ["T",  $text, $is_data]
      ["C",  $text]
      ["D",  $text]
      ["PI", $token0, $text]

    where $attr is a hash reference, $attrseq is an array reference and the rest are plain scalars. The "Argspec" in HTML::Parser explains the details.

で、 'T' だけ $token->[-1] が生のデータじゃないので、特定のタグだけ除去するみたいなことをする場合にここを考慮しないと生のテキストの部分が意図せず省かれてしまう。以下、 a タグを除去しつつ、生のテキストはちゃんと残すサンプル。

gist:146757 · GitHub

#!/usr/bin/env perl
use strict;
use HTML::TokeParser;

my $filename = shift or die;
my $p = HTML::TokeParser->new($filename);

my $html;
while (my $token = $p->get_token) {
    if ($token->[0] eq 'S'
            and $token->[1] eq 'a') {
        # ;;
    }
    else {
        if ($token->[0] eq 'T') {
            $html .= $token->[1];
        }
        else {
            $html .= $token->[-1];
        }
    }
}
print $html;