SimpleXMLで取得したオブジェクトを属性も含めて配列に変換

php5のSimpleXMLエクステンションにてオブジェクトから配列に変換する際、属性値(アトリビュート)も一緒に配列化するのにハマったためメモ

テストで使用したXML

簡単に以下のXMLを定義して、SimpleXMLで読み込みさせてテスト。

<?xml version='1.0'?>
<template>
	<summary>
		<title>タイトル</title>
		<image width="100" height="260">イメージ</image>
		<description>説明</description>
	</summary>
</template>

SimpleXMLでのデータ取得の仕方

参考までにSimpleXMLでのデータの取得の仕方を記述。root要素(例ではtemplateタグ)以下の要素がオブジェクトとして保存されます。

$xml = simplexml_load_string($xmlContent);
//imageタグの中身を取得
echo 'image要素の中身:';
echo $xml->summary->image;
echo '<br />';
//imageのwidth属性を取得
echo 'image要素のwidth属性値:';
echo $xml->summary->image['width'];
echo '<br />';

属性値は配列として取り出します。出力結果は以下。

image要素の中身:イメージ
image要素のwidth属性値:100

SimpleXMLでXMLを読み込んだ場合のデータ構造

例のXMLをvar_dump関数で出力した場合の結果です。

object(SimpleXMLElement)#2 (1) {
  ["summary"]=>
  object(SimpleXMLElement)#1 (3) {
    ["title"]=>
    string(12) "タイトル"
    ["image"]=>
    string(12) "イメージ"
    ["description"]=>
    string(6) "説明"
  }
}

SimpleXMLElementを入れ子構造の配列に変換する関数

image要素の属性値は$arr['image_attrs']['width']のように要素名_attrsで取り出すようになっています。

$result = array();
$result = xml2array(simplexml_load_string($xmlContent));
var_dump($result);

function xml2array($xmlobj) {
	$arr = array();
	if (is_object($xmlobj)) {
		$xml = get_object_vars($xmlobj);
	} else {
		$xml = $xmlobj;
	}

	foreach ($xml as $key => $val) {
		if (is_object($val)) {
			$arr[$key] = xml2array($xmlobj->{$key});
		} else {
			$arr[$key] = $val;
			$attrs = get_object_vars($xmlobj->{$key});
			if (isset($attrs['@attributes'])) {
				$attrs = $attrs['@attributes'];
				$arr[$key.'_attrs'] = $attrs;
			}
		}
	}
	return $arr;
}

var_dumpで出力した結果

array(1) {
  ["summary"]=>
  array(4) {
    ["title"]=>
    string(12) "タイトル"
    ["image"]=>
    string(12) "イメージ"
    ["image_attrs"]=>
    array(2) {
      ["width"]=>
      string(3) "100"
      ["height"]=>
      string(3) "260"
    }
    ["description"]=>
    string(6) "説明"
  }
}

SimpleXMLElementの要素と属性をアンダーバー(_)連結のキー要素の配列に変換する関数

テンプレートエンジンで使用するとき、入れ子構造が複雑だと、かなり使いにくい!

そのため{$image}、{$image_width}、{$image_height}のように、要素名と属性値をアンダーバーで連結させ、単純なループで取り出せるような配列にする関数も作成。

整形しなくてもSmarty(使ってないけど)等で使いやすい形に出力してくれます。

$result = array();
xml2arr($result, simplexml_load_string($xmlContent));
var_dump($result);

function xml2arr(&$arr, $xmlobj, $parent='') {
	if (is_object($xmlobj)) {
		$xml = get_object_vars($xmlobj);
	} else {
		$xml = $xmlobj;
	}
	foreach ($xml as $key => $val) {
		$index = $key;
		if ($parent) {
			$index = $parent.'_'.$key;
		}
		if (is_object($val)) {
			xml2arr($arr, $xmlobj->{$key},$key);
		} else {
			$arr[$index] = $val;
			$attrs = get_object_vars($xmlobj->{$key});
			if (isset($attrs['@attributes'])) {
				$attrs = $attrs['@attributes'];
				foreach($attrs as $attr_key => $attr_val) {
					$arr[$index.'_'.$attr_key] = $attr_val;
				}
			}
		}
	}
}

var_dumpで出力した結果

array(5) {
  ["summary_title"]=>
  string(12) "タイトル"
  ["summary_image"]=>
  string(12) "イメージ"
  ["summary_image_width"]=>
  string(3) "100"
  ["summary_image_height"]=>
  string(3) "260"
  ["summary_description"]=>
  string(6) "説明"
}

最後に

うぉっ、すごく久しぶりにブログを更新しました。。。お客様にはまじめに更新してくださいと依頼しているのになぁ。。。しかも、題材もニッチで自分のお客様になる人対象じゃないという。。。(汗

やはり、自分の好き勝手に更新するのが一番ですよね?(おぃ

それでもネタは溜まっているのにこれは無いだろうと思わなくも無い(汗

ページトップ

ブックマーク!


コメント投稿

* は必須項目です。入力したメールアドレスは公開されません。

*
*



AccessやExcel、.NETソフトウェア開発、WordPress等を使用したWebのシステム化、PCサポート、コンサルなどを行っています。全国対応可能です。お問い合わせください。
TEL (0776)56-8539