PHPでRSSをsimplexml_load_stringなどを使って解析する場合に不正な文字が含まれている時に発生するエラー対処方法のメモです。
厳格なXMLさんのご機嫌をナナメにしてしまう文字列は、RSS発信者の意外な文字列が原因になる場合がほとんどですが、どんなケースでもバシッと取得できるプログラミングをしておきたい所ですね。
XMLの不正文字列をエンコードで排除
文字エンコーディングの「変換⇒再変換」を使って不正な文字列を取り除いてします手法です。
これが正しい方法と言えるのかわかりませんが不正文字をほぼ排除可能なのも事実です。
正常な文字列の破壊もほとんどないので使い道はありそうですね。
$str = mb_convert_encoding($str,'SJIS','UTF-8');
$str = mb_convert_encoding($str,'UTF-8','SJIS');
XMLの不正文字列を正規表現で排除
直接制御文字を正規表現で取り除く手法です。エラーの大半を占める制御文字自体をほぼ排除できますので、以下のようなエラーの場合は解決できるかもしれません。
エラーメッセージ:Entity: line XX: parser error : CData section not finished
エラーメッセージ:Entity: line XX: parser error : PCDATA invalid Char value XX in
$str = preg_replace('/[\x00-\x1f]/','',$str);
XMLに含まれる記号を取り除く
XMLに含まれてしまった記号は思わぬバグに繋がります。その記号自体を直接取り除く手法です。基本的には前述の正規表現と同じですが、エラーの原因がはっきりしている場合には一番手っ取り早いと思います。
見落としやすい「&」が含まれるXMLのエラー対処としても役立ちます。
エラーメッセージ:Entity: line XX: parser error : EntityRef: expecting ‘;’
$str = str_replace('&','&',$str);
XMLに含まれた機種依存文字を取り除く
機種依存文字・特殊記号の含まれるEUC-JPからUTF-8への変換するのですが、SJISを間に挟んでいることがポイントです。なぜなのかと聞かれると長くなりますが、EUCから直接UTF-8に変換だと残ってしまう依存文字も取り除くことができます。
mb_convert_encoding(mb_convert_encoding($str,"sjis-win","EUC-JP"),"UTF-8","sjis-win");
まとめ
今回の紹介は力技が多くなってしまいましたが、機種依存文字などや不正文字への対応を全て記入していくよりも、より効率的な方法になっていると思います。
問題なく動いているPHPがRSS解析でXMLのエラーが突然出てしまった時に個人的に調べまくって結果が出た対処方法になっています。
「なぜそんな文字列を使うの?」と思うようなXMLでも、力技で読み込んでしまいたい時に活躍してくれると思います。
今日も知識欲は止まらない。