Парсинг XML и JSON на PHP
В этой заметке приведены инструкции, как распарсить xml-строку, преобразовать ее в json-объект или ассоциативный массив и получить нужные данные
Задача: есть xml-строка. Нужно распарсить эту строку и вытащить из нее все данные. Пример xml-строки списка товаров
1234
Телефон Nokia
100 у.е.
Пластик
Белый
1024
http://mysite.com/images/photo1.jpg
2096
http://mysite.com/images/photo2.png
24789
Планшет LG
250 у.е.
Металл
Китай
LG
548
http://mysite.com/images/photo10.jpg
Преобразуем xml-строку в json-строку
$xml = simplexml_load_string($xml_string);
$json_string = json_encode($xml);
Дальше у нас 2 варианта, можно преобразовать строку в объект json, а можно в ассоциативный массив. Преобразование выполняет функция json_decode($json_string[, true]). По умолчанию получим объект, но если второй параметр установить в true, то строка преобразуется в ассоциативный массив. На мой взгляд, работать с json-объектом удобнее, но это дело вкуса. Рассмотрим оба варианта
Работаем с объектом
$json = json_decode($json_string);
$goods = $json->goods->good;
foreach($goods as $good) {
echo 'good_id: '.$good->good_id.'
';
echo 'name: '.$good->name.'
';
echo 'price: '.$good->price.'
';
echo 'params:
';
if (isset($good->params->material))
echo '___material: '.$good->params->material.'
';
if (isset($good->params->color))
echo '___color: '.$good->params->color.'
';
if (isset($good->params->country))
echo '___country: '.$good->params->country.'
';
if (isset($good->params->vendor))
echo '___vendor: '.$good->params->vendor.'
';
echo 'photos:
';
$photos = $good->photos->photo;
if(!is_array($photos)) // Если это не массив
$photos = array(0 => $photos);
foreach($photos as $key => $photo) {
echo '___photo number '.strval($key+1).'
';
echo '______size: '.$photo->size.'
';
echo '______url: '.$photo->url.'
';
}
echo '
';
}
Для проверки наличия в узле params нужных свойств используем функцию isset(). Обратите внимание на работу с фото. $good->photos->photo получит разный результат для первого и второго товара. В первом товаре у нас 2 узла photo, и мы получим их массив. Во втором случае узел один, и при этом возвращается объект. Чтобы нам не приходилось вводить условия, как получать информацию, перебором массива или прямым доступом к полям объекта, мы проверяем, является ли полученная переменная массивом, и если нет, "загоняем" ее в массив искусственно. В итоге мы всегда получаем массив с одним или несколькими объектами, которые обрабатываем обычным перебором.
Работаем с массивом
$ar = json_decode($json_string, true);
$goods = $ar['goods']['good'];
foreach($goods as $good) {
echo 'good_id: '.$good['good_id'].'
';
echo 'name: '.$good['name'].'
';
echo 'price: '.$good['price'].'
';
echo 'params:
';
if (isset($good['params']['material']))
echo '___material: '.$good['params']['material'].'
';
if (isset($good['params']['color']))
echo '___color: '.$good['params']['color'].'
';
if (isset($good['params']['country']))
echo '___country: '.$good['params']['country'].'
';
if (isset($good['params']['vendor']))
echo '___vendor: '.$good['params']['vendor'].'
';
echo 'photos:
';
$photos = $good['photos']['photo'];
$keys = array_keys($photos);
if (array_keys($keys) !== $keys) // Если массив ассоциативный
$photos = array(0 => $photos);
foreach($photos as $key => $photo) {
echo '___photo number '.strval($key+1).'
';
echo '______size: '.$photo['size'].'
';
echo '______url: '.$photo['url'].'
';
}
echo '
';
}
Принцип работы точно такой же, только обращаемся мы не к полям объекта, а к значениям массива. Проверка узла photos проходит немного иначе. Код $photos = $good['photos']['photo'] получит в любом случае массив, только нужно определить, является ли он ассоциативным. Соответствующая проверка подсмотрена во фреймворке Kohana
Истории из жизни айти и обсуждение кода.