Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
ラベル array の投稿を表示しています。 すべての投稿を表示
ラベル array の投稿を表示しています。 すべての投稿を表示

2011年3月23日水曜日

PHPの SimpleXMLを配列に変換する

シンプルなXMLなら、SimpleXMLElementオブジェクトをarrayにキャストするだけで連想配列に変換できる。

$xml = '<?xml version="1.0" ?>
<root>
<test>TEST1</test>
<test>TEST2</test>
<attr trouble="MISSING">WHY?</attr>
</root>';

$sx = simplexml_load_string($xml);

var_dump((array)$sx);

array(2) {
  ["test"]=>
  array(2) {
    [0]=>
    string(5) "TEST1"
    [1]=>
    string(5) "TEST2"
  }
  ["attr"]=>
  string(4) "WHY?"
}

同じ要素名の要素がある場合(上記の例ではtest要素)、まとめて添字が0から始まる配列になる。
しかし、なぜか属性とテキストノードの両方がある要素の属性(上記の例ではattr要素のtrouble="MISSING")が無視される。

また、子要素や属性のあるXMLの場合、配列の中まで再帰的にキャストしていないのでSimpleXMLElementのままになってしまう。
$xml = '<?xml version="1.0" ?>
<root>
<parent>
<child>MUSUKO</child>
</parent>
<attr foo="FOO" bar="BAR" />
</root>';

$sx = simplexml_load_string($xml);

var_dump((array)$sx);

array(2) {
  ["parent"]=>
  object(SimpleXMLElement)#3 (1) {
    ["child"]=>
    string(6) "MUSUKO"
  }
  ["attr"]=>
  object(SimpleXMLElement)#2 (1) {
    ["@attributes"]=>
    array(2) {
      ["foo"]=>
      string(3) "FOO"
      ["bar"]=>
      string(3) "BAR"
    }
  }
}




これに対して、PHPマニュアルのコメント欄に一発で配列に変換する方法が書いてあった。
$xml = '<?xml version="1.0" ?>
<root>
<parent>
<child>MUSUKO</child>
</parent>
<attr foo="FOO" bar="BAR" />
</root>';

$sx = simplexml_load_string($xml);

var_dump(json_decode(json_encode($sx), true));

array(2) {
  ["parent"]=>
  array(1) {
    ["child"]=>
    string(6) "MUSUKO"
  }
  ["attr"]=>
  array(1) {
    ["@attributes"]=>
    array(2) {
      ["foo"]=>
      string(3) "FOO"
      ["bar"]=>
      string(3) "BAR"
    }
  }
}



json_decode()の第2引数(戻り値を連想配列にするかどうか)をtrueにするのがポイント。
属性は@attributesというKEYの連想配列に格納される。


しかし、属性とテキストノードの両方がある要素の属性が無視される問題は、このjson_encode/json_decodeを使った方法でも発症する。
$xml = '<?xml version="1.0" ?>
<root>
<attr trouble="MISSING">WHY?</attr>
</root>';

$sx = simplexml_load_string($xml);

var_dump(json_decode(json_encode($sx), true));

array(1) {
  ["attr"]=>
  string(4) "WHY?"
}

Why?
まあでも属性値がないことが分かっているXMLならこれで使えそう。(後から属性値を使いたいということになったら大変だけど。)

きちんとやりたいなら、SimpleXMLで取得したオブジェクトを属性も含めて配列に変換 | とりさんのソフト屋さんのやり方がスマートで良さそう。

2010年12月10日金曜日

PHPで配列と配列を結合する

PHPの配列はarray_merge()でマージできるが、数値のように+演算子でも結合できる。しかし、微妙に結果が違う。


KEYのある配列の場合

//array_merge
var_dump(array_merge(array('foo' => 1, 'bar' => 2), array('foo' => 3, 'baz' => 4)));

array(3) { ["foo"]=> int(3) ["bar"]=> int(2) ["baz"]=> int(4) }

//+演算子
var_dump(array('foo' => 1, 'bar' => 2) + array('foo' => 3, 'baz' => 4));

array(3) { ["foo"]=> int(1) ["bar"]=> int(2) ["baz"]=> int(4) }

同じKEYがある場合、array_merge()だと後の配列で上書きするのに対し、+演算子だと先の配列が勝つようだ。



KEYのない配列の場合
//array_merge
var_dump(array_merge(array('foo', 'bar'), array('foo', 'baz', 'quux')));

array(5) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(3) "foo" [3]=> string(3) "baz" [4]=> string(4) "quux" }

//+演算子
var_dump(array('foo', 'bar') + array('foo', 'baz', 'quux'));

array(3) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(4) "quux" }

array_merge()は全ての配列の値を入れた配列を作ってくれるが、+演算子だとインデックスをKEYとみなして同じインデックスがある限り先の配列の値しか残らない。


基本的にarray_merge()を使う習慣にしておいた方が無難そうだ。



参考:ひとつまたは複数の配列をマージする - PHP 5.3 日本語マニュアル

2010年9月6日月曜日

PHPで変数を arrayや objectにキャストする

PHPでは「$after = (array)$before」のようにカッコ付きで型を指定しればデータをキャスト(型変換)できる。
特に、配列の場合とそうでない場合の両方あり得るデータを配列として扱うのに便利。

$arr = (array)$array_or_not;

以下は、配列やobjectにキャストするとどうなるかの実験結果。
//配列にキャスト
var_dump((array)123);         // => array(1) { [0]=>  int(123) }

//配列を配列にキャスト
var_dump((array)array(123));  // => array(1) { [0]=>  int(123) }

//Objectにキャスト
var_dump((object)123);        // => object(stdClass)#1 (1) { ["scalar"]=>  int(123) }

//配列をObjectにキャスト
var_dump((object)array(123)); // => object(stdClass)#1 (1) { [0]=>  int(123) }

//Objectを配列にキャスト
var_dump((array)(object)123); // => array(1) { ["scalar"]=>  int(123) }

2010年6月15日火曜日

PHPの json_encode()で配列になるかハッシュになるか

json_encode()でPHPの配列をJSONにする場合に、PHPの配列の内容によってJSONの配列(Array)になるかハッシュ(JSONの場合KEYが文字列のプロパティの集合)になるかを調べてみた。


PHPの連想配列(KEYあり)の場合

$arr = array('foo' => 'a', 'bar' => 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","bar":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列(KEY指定なし=ゼロから始まる連番)の場合
$arr = array('a', 'b', 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの配列を、json_encode()のオプション指定で強制的にハッシュにした場合
$arr = array('a', 'b', 'c');
echo json_encode($arr, JSON_FORCE_OBJECT);
// => {"0":"a","1":"b","2":"c"}
→JSONのハッシュになった。


PHPの連想配列で、一部だけKEY指定なしの場合
$arr = array('foo' => 'a', 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","0":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列から最初の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[0]);
echo json_encode($arr);
// => {"1":"b","2":"c"}
→JSONのハッシュになった。


PHPの配列から最初 途中の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[1]);
echo json_encode($arr);
// => {"0":"a","2":"c"}
→JSONのハッシュになった。


PHPの配列から最後の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[2]);
echo json_encode($arr);
// => ["a","b"]
→JSONの配列になった!


PHPの連想配列でKEYをゼロから始まる連番で指定した場合
$arr = array(0 => 'a', 1 => 'b', 2 => 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの連想配列でKEYを数値だけど連番じゃないものにした場合
$arr = array(0 => 'a', 1 => 'b', 4 => 'c');
echo json_encode($arr);
// => {"0":"a","1":"b","4":"c"}
→JSONのハッシュになった。



結論
json_encode()により配列(Array)になるのは、PHPの(連想)配列のKEYがゼロから始まる連番の場合のみ

ブログ アーカイブ

tags