人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHP の simplexml_load_string のエラーがキャッチできない
現在、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形式なのか?そうでないのか? が
判る方法を教えて下さい。

●質問者: Makoto
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● a-kuma3
ベストアンサー

例外を出さないんだそうです。

他パースエラーが発生した場合の原因がわからない

上記の制御文字コードをエラーとして試しに出力しようとしたら、
try catchで例外としてキャッチできなかった。
どうやら warning エラー。
参考:php - How do I handle Warning: SimpleXMLElement::__construct()? - Stack Overflow
set_error_handler を使う。

PHPでのXMLパースエラー出力は必須だね - 今からお前んちこいよ

エラーハンドラで例外を投げるようにすると、今 書いているであろうコードがそのまま使えそうです。


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 のはずなんだけど、タグが崩れてる、とかには使えませんが。


Makotoさんのコメント
ありがとうございます。ただ、ここまで実装しても、エラーをキャッチできません。 正直お手上げです。 https://gist.github.com/hamaguchi/7925cdac57dcc116ae14

a-kuma3さんのコメント
>|| set_error_handler(function($errno, $errstr, $errfile, $errline) { throw new \Exception($errstr, $errno); /* ↑これ */ }); ||< set_error_handler 内で、Exception の前にバックスラッシュがついてますが、このせいで例外が送出されないのではないですか?

a-kuma3さんのコメント
あ、バックスラッシュは名前空間なのか……

a-kuma3さんのコメント
Exception にグローバルな名前空間をつけなければいけないソースなら、catch するところにも必要なんじゃないでしょうか。

Makotoさんのコメント
ちなみに、FuelPHPで組んでいます。 バックスラッシュは、必要ありませんでした。function で外出ししたら、バックスラッシュに関するエラーは出なくなりました。 また、やっとエラーがでる原因のRSS URLが分かり、解析したところ UTF-16 でした。RSSでまさかのUTF-16...サクッと削除し、エラーが出なくなりました。 ただ、実際にエラーが出た場合は、ハンドリングできないような・・・。困りました。

a-kuma3さんのコメント
その 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/

質問者から

ここまで、実装しましたが、エラーがキャッチできません。
謎すぎ・・・

https://gist.github.com/hamaguchi/7925cdac57dcc116ae14


2 ● syamaoka

エラーを判別する方法は、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 を使う必要があります。

関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ