[PHP-users 27375] マルチバイトのHTMLをloadHTMLするとDOMとして解析できない

Hiroshi Yamada hiroshikun @ aol.com
2005年 11月 4日 (金) 21:30:17 JST


山田と申します。よろしくお願いします。

さて、VineLinux3.1 PHP5.0.5上でHTMLを解析して主にテーブルのデータを整理する
プログラムを考えています。
そこでXML::DOMを利用しようとしているのですが、UTF-8で、

<?php
mb_language('Japanese');
mb_internal_encoding("UTF-8");
ini_set("mbstring.http_output","UTF-8");

header("Content-Type: text/html; charset=UTF-8");

$HTML=<<<EOT
<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>DOMテスト</TITLE>
</HEAD>
<BODY>
テストデータ
</BODY>
</HTML>
EOT;
$doc=new DOMDocument("1.0","UTF-8");
$doc->loadHTML($HTML);
echo $doc->saveHTML();

?>

と書いてブラウザで表示するとうまくいきます。
しかし解析対象のHTMLはShift_JISだったりEUCだったりするので、EUC-JPで

<?php
mb_language('Japanese');
mb_internal_encoding("UTF-8");
ini_set("mbstring.http_output","UTF-8");

header("Content-Type: text/html; charset=UTF-8");

$HTML=<<<EOT
<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<TITLE>DOMテスト</TITLE>
</HEAD>
<BODY>
テストデータ
</BODY>
</HTML>
EOT;
$HTML=mb_convert_encoding($HTML,"UTF-8","EUC-JP");
$doc=new DOMDocument("1.0","UTF-8");
$doc->loadHTML($HTML);
echo $doc->saveHTML();

?>

としてもエラーがでたり、文字化けした状態で表示されます。どうやら
mb_convert_encodingした文字列をDOMDocumentに放り込んだ段階でおかしくなってい
るようです(実際のデータをfile_get_contentsするとタグの閉じ忘れなどの警告が
かなりでるのですが他のサイトのデータなので修正はできません)。
"charset=EUC-JP"を"charset=UTF-8"に書き直してDOMDocumentに放り込んでもやは
り、きれいに格納してくれません。
Shift_JISを試行錯誤の結果、コンバートして格納できノードの操作ができた例もあ
るのですが、UTF-8のページをコンバートせずに格納してもうまく行かないなど
DOMDocumentの挙動がさっぱりわからず途方に暮れています。iconvを使って文字コー
ドをコンバートしたり、libXML2のバージョンアップやphp.iniの設定などいろいろ変
えましたが解決策が見つかりません。
Googleで検索したところ同じような問題で中国簡体字のケースで質問をしている方が
いましたが解決されていないようです。
やはり、Well-FormedでないHTMLをDOMDocumentで解析するのは難しいのでしょうか?
 VBアプリでMSXMLライブラリを使ったところ日本語でもうまく動いたのでPHPでもで
きると思ったのですが...

php.iniのマルチバイト関係は現在以下の設定です。

default_charset = EUC-JP
output_handler = mb_output_handler
mbstring.language = Japanese
mbstring.http_input = auto
mbstring.http_output = EUC-JP
mbstring.encoding_translation = On
mbstring.detect_order = auto
mbstring.substitute_character = none

なにか解決の糸口をご存じの方がいらっしゃいましたら、よろしくお願いします。




PHP-users メーリングリストの案内