PHPとXMLの連携のときにアットライズのサーバーで起こったバグ的なPHPの処理の不具合メモだよ。

デフォルトのデータ処理

デフォルトのデータ処理はなぜか途中で終わってしまうものが
あったので、$tmp[$name]に追加する形で入れる。
途中で終わった場合でも終了タグがきたわけではないので、
再びデフォルトの処理に戻ってくる。

その後、終了タグが来たときに$tmp[$name]をその要素の配列に
入れて、$tmp[$name]を初期化してあげる

という処理をしてあげると良いということがわかったよ。

詳しくは続きを読むをクリック!

//開始要素
function start_el($ps,$name,$atr){
global $map_array,$tag,$depth,$parent,$first_child,$second_child;

$first_child = 2;
$second_child = 3;

if(isset($map_array[$name])){
//echo “[".$depth[$ps].”]”;

//深度が1だった場合は$parentに$nameを代入
if($depth[$ps] == $first_child):
$parent = $name;
endif;
//echo $name.”<br>”;
$tag = $name;
}else{
$tag = “”;
}

$depth[$ps]++;
}

//終了要素
function end_el($ps,$name){
global $map_array,$depth,$tmp,$parent,$blog,$first_child,$second_child,$blog_title,$blog_url,$link_url;
$depth[$ps]–;

if(isset($map_array[$name])){

if($depth[$ps] == $first_child):
if($name == “TITLE”):

$blog_title = mb_convert_encoding($tmp[$name],”SJIS”,”auto”);
$tmp[$name] = “”;
elseif($name == “LINK”):
$blog_url = $tmp[$name];
$tmp[$name] = “”;
endif;
elseif($depth[$ps] == $second_child):
if($name == “TITLE”):
$blog[blog_title][] = $blog_title;
$blog[blog_url][] = $blog_url;
$blog[entry_title][] = $tmp[$name];
$tmp[$name] = “”;
elseif($name == “LINK”):
$blog[entry_url][] = $tmp[$name];
$tmp[$name] = “”;
elseif($name == “PUBDATE”):
$blog[entry_date][] = date(“Y/m/d”,strtotime($tmp[$name]));
$tmp[$name] = “”;
endif;

endif;

//endif;

}
}

//デフォルトデータ処理
function char_data($ps,$data){
global $tmp,$tag,$depth,$link_url;

if($tag != “”):
$tmp[$tag] .= mb_convert_encoding($data,”SJIS”,”auto”);

endif;
}

//XMLの処理

//XMLパーサ作成
$xml = xml_parser_create();

//開始要素、終了要素の処理を指定
xml_set_element_handler($xml,”start_el”,”end_el”);

//デフォルトの処理を指定する
xml_set_character_data_handler($xml,”char_data”);

//XMLファイルを展開して処理する
while ($data = fread($file,1000)):
if(!xml_parse($xml,$data,feof($file))):
die(“<p>エラー行番号:”.xml_get_current_line_number($xml));
endif;
endwhile;

いろんなところからパクっ。。。もとい、たくさんの親切な方々のソースを参考にさせていただいたのでつぎはぎだらけで、自分でもよくわからないところが多 々あるのだけども要するにXMLの開始タグがきたら、start_elを実行、終了タグが着たらend_elを実行、それ以外は、デフォルトの処理であ る、char_dataを実行するという感じらしい。

で、問題のデフォルトデータの処理だけれども、RSSのXMLを読み込む時にLINKの中身がなぜか途中で終わってしまうような形のもの がたまに出てきてしまうので、それを回避するために、$tmp[$tag]に一時的に保存をしてあげる。デフォルトの処理が途中で終わっても、終了タグは まだ来ないからデータを表示するための配列$blog[element名]にはまだデータは入らないので、一時保存の$tmp[$tag]に追加をするよ うに$tmp[$tag] .= データ;としてあげる。

終了タグが来たら一時保存のデータを表示用の配列に入れてあげて、一時保存の配列を初期化してあげる。

というようにしてあげることで、まんまとうまくいくのでした。

ちなみに、不具合が見られたのは、LINKとPUBDATEのところで、実はRDFのフィードしか読んでいないのだけども、RSSやATOMフィードの場合はブログタイトルだとか、 エントリータイトルにも同じような現象が見られた。

おそらくPHPのバージョンが影響していると思われるのだけども、念のためのメモ。

[関連性があるかもしれない記事]

  1. 今日はじめて知ったPHPのMySQLな関数
  2. PHPで日本語を使うのだ
  3. PHPメモ:mb_convert_encodingの挙動
  4. PHPのユーザー定義関数で複数の戻り値がほしいんだ!
  5. デザイナーのためのPHP