PHPの組み込み関数にもXMLをパースする関数があるけど、自分で実装したくなったので自分で書いてみたよ。
APIから返されるXMLの構造が微妙に難しかったので、再帰関数とスタックでやってみた。
APIのURLは→「http://webservice.d-064.com/3.x/category.xml」です。
/** 電脳卸用全てのカテゴリをパースして配列して、シリアライズ後保存する。 パース結果の配列は以下のような仕様で出力される 結果配列仕様: array( 'カテゴリID 1' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) ); array( 'カテゴリID 2' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) ); array( 'カテゴリID 3' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) ); ... array( 'カテゴリID n' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) ); ※一番上のカテゴリは親カテゴリIDが「-1」となっている。 商品のカテゴリIDから親カテゴリ全てを取得するには、 function get_category_tree( $category_id, &$category_tree ) { global $global_category_array; $id = $category_id; $name = $global_category_array[ $id ][ 'name' ]; $parent = $global_category_array[ $id ][ 'parent' ]; $category_tree[ $id ] = array( 'name' => $name, 'parent' => $parent ); if( $parent == '-1' ) { return ; } else { get_category_tree( $parent, $category_tree ); } } $global_category_array = unserialize( file_get_contents( './category_array.dat' ) ); $tree = array(); get_category_tree( '1269', $tree ); var_dump( $tree ); といったプログラムで返せる。 */ define( 'CATEGORY_XML_URL', 'http://webservice.d-064.com/3.x/category.xml' ); define( 'CATEGORY_XML_FILENAME', dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'category.xml' ); define( 'CATEGORY_ARRAY_FILENAME', dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'category_array.dat' ); define( 'CATEGORY_SRC_ENCODING', 'UTF-8' ); define( 'CATEGORY_DIST_ENCODING', 'SJIS' ); date_default_timezone_set( 'Asia/Tokyo' ); /* 個々のカテゴリデータを取得する @return array [ 'category_id', 'category_depth', 'category_name' ] */ function get_id_depth_name() { global $xmlp; return array( preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ), // カテゴリID preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ), // カテゴリ深さ preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ) ); // カテゴリ名 } /** カテゴリXMLをパースする。再帰関数。 @param $parent 親カテゴリID */ function parse( $parent = -1 ) { global $xmlp; global $global_category_array; global $global_parent_ids; // 親IDのスタック $line = trim( fgets( $xmlp ) ); switch( true ) { // 空行 case ($line == ''): parse( $parent ); break; // XML定義 case preg_match( '/<\?xml(?:[^>]+)>/', $line ): parse( $parent ); break; // 一番外側のタグ case ($line == ''): parse( $parent ); break; case ($line == ' '): fclose( $xmlp ); return; // 1つのカテゴリ case ($line == ''): list( $id, $depth, $name ) = get_id_depth_name(); $name = mb_convert_encoding( $name, CATEGORY_DIST_ENCODING, CATEGORY_SRC_ENCODING ); // 親IDを退避 $parent = $global_parent_ids[ 0 ]; // スタックに自分を積む array_unshift( $global_parent_ids, $id ); $global_category_array[ $id ][ 'name' ] = $name; $global_category_array[ $id ][ 'parent' ] = $parent; parse( $parent ); break; case ($line == ' '): // 自分のIDを捨てる array_shift( $global_parent_ids ); parse( $global_parent_ids[ 0 ] ); break; // サブカテゴリ case ($line == ''): parse( $global_parent_ids[ 0 ] ); break; case ($line == ' '): parse( $global_parent_ids[ 0 ] ); break; // ファイルが終わる前に「/Categorys」が来るはずなので使わないかも。 case feof( $xmlp ): fclose( $xmlp ); return; // 何かあったときのための保険。そのまま終了。 default: die( '[' . $line . '] Exception.' ); } } // XMLファイルダウンロードと保存 file_put_contents( CATEGORY_XML_FILENAME, file_get_contents( CATEGORY_XML_URL ) ); // XMLファイルのポインタ取得 $xmlp = fopen( CATEGORY_XML_FILENAME, 'r' ); if( !$xmlp ) { die( 'XML File Dont Open.' ); } // 親IDスタックと結果配列準備 $global_parent_ids = array( -1 ); $global_category_array = array(); // パース本体 parse(); // 結果配列をシリアライズして保存 file_put_contents( CATEGORY_ARRAY_FILENAME, serialize( $global_category_array ) ); exit( 0 );
こんな感じ。