tokuhirom's Blog

HTML::Tree 4.0 での互換性のない変更だとおもったらバグだたのでパッチをおくったメモ

【追記 2010-09-27】
HTML::Tree にバグをみつけたので、パッチをおくりました、それがリリースされるまでの間は HTML::Tree 4.0 はつかわない方がいいです。


全然まとまった内容ではないのですが、現状を記す。

4.0    Mon Sep 20 2010
    [THINGS THAT MAY BREAK YOUR CODE OR TESTS]
    * Changes to entity encoding from ord values to XML entities may break
      tests expecting � style encoding.
    * Attribute names are now validated in as_XML and invalid names will
      cause an error.

http://cpansearch.perl.org/src/JFEARN/HTML-Tree-4.0/Changes

HTML::Tree 4.0 では上記の incompatible change がはいっている。特に後者の変更が重要だ。

use HTML::TreeBuilder;

print HTML::TreeBuilder->VERSION, $/;

my $tree = HTML::TreeBuilder->new();
$tree->parse(q{<img src="foo.gif" />});
print $tree->as_XML();
$tree = $tree->delete;

というスクリプトが、3.23 では以下のようになるが

3.23
<html><head></head><body><img src="foo.gif" /></body></html>

4.0 では以下のようになる。

4.0
img has an invalid attribute name '/' at hoge.pl line 7

対策としては as_HTML() method をつかえばよい。

ただしここで、Web::Scraper は 'raw' または 'html' モードの時に ->as_XML を call しているので、これが問題だなあとおもっている。

対策編

as_HTML をつかう

とりあえず as_HTML では validation していないし問題ないので、問題とならない。

HTML::TreeBuilder::XPath->as_XML_compact() をつかう

このメソッドでは validation をおこなっていないので問題がおきない。
Web::Scraper ではこの方法がよいのではないか。

そもそも attr に '/' がはいっているのがおかしいという説
use HTML::TreeBuilder::XPath;
use Data::Dumper;

print HTML::TreeBuilder->VERSION, $/;

{
    my $tree = HTML::TreeBuilder::XPath->new();
    $tree->parse(<<'...');
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
    <title>XHTML</title>
</head>
<body>
    <img src="foo.gif" />
</body>
</html>
...
    my ($node) = $tree->findnodes('//img');
    print Dumper(+{ $node->all_external_attr });
}

の結果をみると

4.0
$VAR1 = {
          '/' => '/',
          'src' => 'foo.gif'
        };

となるわけだが、そもそも '/'='/' という attr がはいっているのがおかしいのではないか。

まとめ

まとまってません。

さらにまとめ

http://github.com/jfearn/HTML-Tree/pull/1
しらべてみたら結局、HTML::Tree のバグだという結論にたっしたので、パッチをかいて pull request しておきました。

ほぼほぼこれでマージされるとおもうので、それがリリースされるまでの間は HTML::Tree はアップデートしない方がいいかもです。