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形式なのか?そうでないのか? が
判る方法を教えて下さい。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2015/02/13 11:10:03

ベストアンサー

id:a-kuma3 No.1

回答回数4974ベストアンサー獲得回数2154

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

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

上記の制御文字コードをエラーとして試しに出力しようとしたら、
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 のはずなんだけど、タグが崩れてる、とかには使えませんが。

他4件のコメントを見る
id:makoto1899

ちなみに、FuelPHPで組んでいます。

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

2015/02/06 13:49:51
id:a-kuma3

その UTF-16 な RSS を処理しようとしたら、きちんと例外が出て、例外を捕捉できたってことですよね。

万能じゃないと思いますが、utf8_encode() を使え、みたいな書き込みがちらほらとあります。

2015/02/06 16:37:29

その他の回答1件)

id:a-kuma3 No.1

回答回数4974ベストアンサー獲得回数2154ここでベストアンサー

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

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

上記の制御文字コードをエラーとして試しに出力しようとしたら、
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 のはずなんだけど、タグが崩れてる、とかには使えませんが。

他4件のコメントを見る
id:makoto1899

ちなみに、FuelPHPで組んでいます。

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

2015/02/06 13:49:51
id:a-kuma3

その UTF-16 な RSS を処理しようとしたら、きちんと例外が出て、例外を捕捉できたってことですよね。

万能じゃないと思いますが、utf8_encode() を使え、みたいな書き込みがちらほらとあります。

2015/02/06 16:37:29
id:makoto1899

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

謎すぎ・・・

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

id:syamaoka No.2

回答回数21ベストアンサー獲得回数9

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

  • id:tobeoscontinue
    $xml = @simplexml_load_string($xml_context);
    オーバーヘッドがあるようですがエラー制御演算子を使って無視する方法はどうでしょう。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません