PHPのsimplexml_load_file()でXMLを扱うときに注意すること
はじめに
XMLは、JSONと違って同じ名前の要素を複数持つことができるのですが、PHPのsimplexml_load_file関数で扱うときにちょっとめんどくさかったのでメモ。
もっといい解決策があるかもしれません。
実験
入力XML
list1.xml
<?xml version="1.0" encoding="utf-8"?> <data> <book> <title>Swiftではじめる iPhoneアプリ開発の教科書</title> <caption>Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。</caption> <date>2015/10/30</date> </book> </data>
list2.xml
<?xml version="1.0" encoding="utf-8"?> <data> <book> <title>詳細! Swift 2 iPhoneアプリ開発 入門ノート</title> <caption>待ったなし! Swift 2</caption> <date>2015/11/14</date> </book> <book> <title>Swiftではじめる iPhoneアプリ開発の教科書</title> <caption>Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。</caption> <date>2015/10/30</date> </book> </data>
list1.xmlはbookタグが1個、list2.xmlはbookタグが2個存在します。
コード1
<?php $xml1 = simplexml_load_file('./list1.xml'); $xml2 = simplexml_load_file('./list2.xml'); $xml_array1 = json_decode(json_encode($xml1), true); $xml_array2 = json_decode(json_encode($xml2), true); print_r($xml_array1); print_r($xml_array2);
SimpleXMLElementオブジェクトを配列に変換する方法は、公式ドキュメントのコメントを参考に。
json_decodeの第2引数をtrue
にすることで連想配列にしています。
結果
temp $ php xml2array1.php Array ( [book] => Array //連想配列 ( [title] => Swiftではじめる iPhoneアプリ開発の教科書 [caption] => Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。 [date] => 2015/10/30 ) ) Array ( [book] => Array //連想配列の配列 ( [0] => Array ( [title] => 詳細! Swift 2 iPhoneアプリ開発 入門ノート [caption] => 待ったなし! Swift 2 [date] => 2015/11/14 ) [1] => Array ( [title] => Swiftではじめる iPhoneアプリ開発の教科書 [caption] => Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。 [date] => 2015/10/30 ) ) ) temp $
book要素が1個の場合と2個の場合で結果が異なります。 これでは、viewに表示するときなどに困りますね。
コード2
<?php $xml1 = simplexml_load_file('./list1.xml'); $xml_array1 = json_decode(json_encode($xml1), true); print_r($xml_array1); foreach($xml_array1 as $key => $value) { // 連想配列だったら配列に変換 if (is_array($value) && array_values($value) !== $value) { if (array_values($value) !== $value) { $xml_array1 = array($key => array($value)); } } print_r($xml_array1);
結果
temp $ php xml2array2.php Array ( [book] => Array ( [title] => Swiftではじめる iPhoneアプリ開発の教科書 [caption] => Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。 [date] => 2015/10/30 ) ) Array ( [book] => Array //要素1の連想配列の配列 ( [0] => Array ( [title] => Swiftではじめる iPhoneアプリ開発の教科書 [caption] => Appleのプログラミング言語、「Swift」バージョン2対応の、iPhoneアプリ作成入門書です。 [date] => 2015/10/30 ) ) ) temp $
これで同じ構造になりました。
おまけ
if (array_values($value) !== $value)
は何をしているのか。
公式ドキュメントからこの関数の説明を引用します。
array_values() は、配列 array から全ての値を取り出し、数値添字をつけた配列を返します。
つまり、配列の場合はarray_valuesを使っても何も変わりませんが、連想配列であれは値だけになると!==
となるので、連想配列かどうかを判定できます。