@kyanny's blog

世界に対して侵略は成功しないということを示す義務がある。もはや誰かが決断しなければならない - マーガレット・サッチャー

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 が入るということらしい。


    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;