現在、PHP の simplexml_load_string で、RSSファイルを読み込ませて、
解析するプログラムを作っています。一部、読み込めないRSSがあり、
>Uncaught exception Exception: simplexml_load_string(): Entity: line 1: parser error :
>Start tag expected, '<' not found
というエラーが出ています。このエラーを判る方法(キャッチする)を教えて下さい。
または、file_get_contents したXML形式のstringを、XML形式なのか?そうでないのか? が
判る方法を教えて下さい。
例外を出さないんだそうです。
他パースエラーが発生した場合の原因がわからない
上記の制御文字コードをエラーとして試しに出力しようとしたら、
PHPでのXMLパースエラー出力は必須だね - 今からお前んちこいよ
try catchで例外としてキャッチできなかった。
どうやら warning エラー。
参考:php - How do I handle Warning: SimpleXMLElement::__construct()? - Stack Overflow
set_error_handler を使う。
エラーハンドラで例外を投げるようにすると、今 書いているであろうコードがそのまま使えそうです。
php のマニュアルには、こんなことが書いてあります。
エラー / 例外 ¶
XML データ内でエラーが見つかるたびに E_WARNING エラーメッセージが発生します。
ヒント libxml_use_internal_errors() ですべての XML エラーを抑制し、 後から libxml_get_errors() で取得することもできます。
PHP: simplexml_load_string - Manual
「ヒント」の部分について、具体的なコードは、マニュアルの libxml_get_errors() に記載があります。
または、file_get_contents したXML形式のstringを、XML形式なのか?そうでないのか? が
判る方法を教えて下さい。
あくまでも簡易的な方法ですけど、先頭が XML宣言になっているかどうかで判断できます。
先頭の 5byte が "<?xml" かどうかで判定します。
# XML のはずなんだけど、タグが崩れてる、とかには使えませんが。
例外を出さないんだそうです。
他パースエラーが発生した場合の原因がわからない
上記の制御文字コードをエラーとして試しに出力しようとしたら、
PHPでのXMLパースエラー出力は必須だね - 今からお前んちこいよ
try catchで例外としてキャッチできなかった。
どうやら warning エラー。
参考:php - How do I handle Warning: SimpleXMLElement::__construct()? - Stack Overflow
set_error_handler を使う。
エラーハンドラで例外を投げるようにすると、今 書いているであろうコードがそのまま使えそうです。
php のマニュアルには、こんなことが書いてあります。
エラー / 例外 ¶
XML データ内でエラーが見つかるたびに E_WARNING エラーメッセージが発生します。
ヒント libxml_use_internal_errors() ですべての XML エラーを抑制し、 後から libxml_get_errors() で取得することもできます。
PHP: simplexml_load_string - Manual
「ヒント」の部分について、具体的なコードは、マニュアルの libxml_get_errors() に記載があります。
または、file_get_contents したXML形式のstringを、XML形式なのか?そうでないのか? が
判る方法を教えて下さい。
あくまでも簡易的な方法ですけど、先頭が XML宣言になっているかどうかで判断できます。
先頭の 5byte が "<?xml" かどうかで判定します。
# XML のはずなんだけど、タグが崩れてる、とかには使えませんが。
ちなみに、FuelPHPで組んでいます。
バックスラッシュは、必要ありませんでした。function で外出ししたら、バックスラッシュに関するエラーは出なくなりました。
また、やっとエラーがでる原因のRSS URLが分かり、解析したところ UTF-16 でした。RSSでまさかのUTF-16...サクッと削除し、エラーが出なくなりました。
ただ、実際にエラーが出た場合は、ハンドリングできないような・・・。困りました。
その UTF-16 な RSS を処理しようとしたら、きちんと例外が出て、例外を捕捉できたってことですよね。
万能じゃないと思いますが、utf8_encode() を使え、みたいな書き込みがちらほらとあります。
エラーを判別する方法は、libxml_use_internal_errors を呼んでから libxml_get_errors で取得した配列が空か否かを確認する、ということになるでしょうか。
エラー自体を回避するには、
1. HTTP レスポンスの Content-Type から符号化方式を判別する
2. mb_convert_encoding で特定した符号化方式から UTF-8 にレスポンスを変換する(HTTP の仕様上、レスポンスに UTF-16 を使用する場合 Network Byte Order を使用しなければならないらしいので、UTF-16BE から UTF-8 に変換することになります。)
3. 変換後のレスポンスに対して simplexml_load_string を呼ぶ
という手順はどうでしょう。この場合、HTTP レスポンスの header を知る必要があるため file_get_contents で XML を取得することはできません。別途ライブラリか curl extension を使う必要があります。
ちなみに、FuelPHPで組んでいます。
2015/02/06 13:49:51バックスラッシュは、必要ありませんでした。function で外出ししたら、バックスラッシュに関するエラーは出なくなりました。
また、やっとエラーがでる原因のRSS URLが分かり、解析したところ UTF-16 でした。RSSでまさかのUTF-16...サクッと削除し、エラーが出なくなりました。
ただ、実際にエラーが出た場合は、ハンドリングできないような・・・。困りました。
その UTF-16 な RSS を処理しようとしたら、きちんと例外が出て、例外を捕捉できたってことですよね。
万能じゃないと思いますが、utf8_encode() を使え、みたいな書き込みがちらほらとあります。
- http://stackoverflow.com/questions/2507608/error-input-is-not-proper-utf-8-indicate-encoding-using-phps-simplexml-lo
- http://www.binarytides.com/php-fix-input-is-not-proper-utf-8-indicate-encoding-error-when-loading-xml/
2015/02/06 16:37:29