SimpleXML. Начало работы
24.04.2013
Теги: PHP • Web-разработка • XML
Расширение SimpleXML предоставляет очень простой и легкий в использовании набор инструментов для преобразования XML в объект, с которым можно затем работать через его свойства и с помощью итераторов. SimpleXML присутствует в PHP начиная с версии 5.
Для наглядности, в качестве примера будем использовать XML, описывающий простой кулинарный рецепт, взятый с википедии.
<?xml version="1.0" encoding="UTF-8"?>
<recipe name="хлеб" preptime="5" cooktime="180">
<title>Простой хлеб</title>
<ingredient amount="3" unit="стакан">Мука</ingredient>
<ingredient amount="0.25" unit="грамм">Дрожжи</ingredient>
<ingredient amount="1.5" unit="стакан">Тёплая вода</ingredient>
<ingredient amount="1" unit="чайная ложка">Соль</ingredient>
<instructions>
<step>Смешать все ингредиенты и тщательно замесить.</step>
<step>Закрыть тканью и оставить на один час в тёплом помещении.</step>
<step>Замесить ещё раз, положить на противень и поставить в духовку.</step>
</instructions>
</recipe>
Загрузка XML
Прежде чем начать обрабатывать данные, их нужно сначала загрузить. Для этого достаточно использовать функцию simplexml_load_file(). Она принимает имя файла, и возвращает объект типа SimpleXMLElement. И с этим объектом уже можно будет работать.
$xml = simplexml_load_file('recipe.xml'); print_r($xml);
SimpleXMLElement Object ( [@attributes] => Array ( [name] => хлеб [preptime] => 5 [cooktime] => 180 ) [title] => Простой хлеб [ingredient] => Array ( [0] => Мука [1] => Дрожжи [2] => Тёплая вода [3] => Соль ) [instructions] => SimpleXMLElement Object ( [step] => Array ( [0] => Смешать все ингредиенты и тщательно замесить. [1] => Закрыть тканью и оставить на один час в тёплом помещении. [2] => Замесить ещё раз, положить на противень и поставить в духовку. ) ) )
Кроме того, существует еще и функция simplexml_load_string(), которая берет XML не из файла, а из строки.
$str = file_get_contents('recipe.xml'); $xml = simplexml_load_string($str);
Получение данных
SimpleXML предоставляет очень удобный способ получения данных из XML. К примеру, для того чтобы получить какой-либо узел документа достаточно просто обратится к этому узлу по имени:
// Выводит содержимое элемента <title> echo $xml->title;
Поскольку ингредиентов у нас несколько, то $xml->ingredient будет массивом из четырех элементов. Перебрать все ингредиенты можно так:
foreach ( $xml->ingredient as $ingredient ) { echo $ingredient . '<br/>'; }
Для того что бы получить, к примеру, третий ингредиент (теплая вода), достаточно обратиться к нему по индексу:
$xml->ingredient[2]; // элементы массивы нумеруются с нуля
Шаги приготовления (step) являются дочерними для элемента instructions, чтобы получить их, нужно сначала получить instructions:
echo $xml->instructions->step; // выводит текст первого шага
Атрибуты
Работать с атрибутами тоже очень легко. Они доступны как ассоциативный массив своего элемента. То есть, для того что бы получить название рецепта (атрибут name корневого узла recipe), достаточно написать:
echo $xml['name'];
Или, для получения количества первого ингредиента можно написать так:
echo $xml->ingredient['amount'];
Сейчас мы рассмотрели только один способ получения данных: когда нам уже известны названия узлов и атрибутов. Но случается и так, когда структура XML файла заранее не известна, но нам нужно его обработать. SimpleXML предоставляет и такую возможность.
Получение дочерних узлов
Метод children() возвращает список дочерних элементов. В нашем случае $xml — корневая ветвь, и если написать:
$nodes = $xml->children(); echo $nodes[0];
то получим содержимое элемента <title>, а если:
$nodes = $xml->children(); echo $nodes[2];
то второй ингредиент.
Обойти все дочерние ветви первого уровня легко можно при помощи цикла foreach:
echo '<ul>'; foreach ( $xml->children() as $node ) { if ( count($node) == 0 ) echo '<li>' . $node . '</li>'; } echo '</ul>';
Результат:
<ul> <li>Простой хлеб</li> <li>Мука</li> <li>Дрожжи</li> <li>Тёплая вода</li> <li>Соль</li> </ul>
Фукция count() позволяет определить количество дочерних узлов.
Для того, чтобы получить имя текущий ветви, используется метод getName():
$nodes = $xml->children(); echo $nodes[0]->getName(); // выведет title
Получение атрибутов
Получить список атрибутов для текущего элемента поможет метод attributes(). По функционалу и механизму работы он аналогичен методу children(), за тем исключением, что здесь идет работа с атрибутами.
$nodes = $xml->children(); // все атрибуты узла <ingredient>Мука</ingredient> foreach ( $nodes[1]->attributes() as $name => $value ) { echo 'атрибут ' . $name . ', значение ' . $value . '<br/>'; }
Результат:
атрибут amount, значение 3<br/> атрибут unit, значение стакан<br/>
Изменение значений узлов и атрибутов
Объект SimpleXMLElement позволяет манипулировать всеми элементами:
$xml = simplexml_load_file('recipe.xml'); $xml->title = 'Ржаной хлеб'; $xml->ingredient[0] = 'Ржаная мука'; print_r($xml); $xml->ingredient[2]['amount'] = '300'; $xml->ingredient[2]['unit'] = 'грамм'; print_r($xml->ingredient[2]);
Результат:
SimpleXMLElement Object ( [@attributes] => Array ( [name] => хлеб [preptime] => 5 [cooktime] => 180 ) [title] => Ржаной хлеб [ingredient] => Array ( [0] => Ржаная мука [1] => Дрожжи [2] => Тёплая вода [3] => Соль ) [instructions] => SimpleXMLElement Object ( [step] => Array ( [0] => Смешать все ингредиенты и тщательно замесить. [1] => Закрыть тканью и оставить на один час в тёплом помещении. [2] => Замесить ещё раз, положить на противень и поставить в духовку. ) ) )
SimpleXMLElement Object ( [@attributes] => Array ( [amount] => 300 [unit] => грамм ) [0] => Тёплая вода )
Добавление элементов и атрибутов
Чтобы добавить дочерний элемент к текущему, достаточно использовать метод addChild(). Первым параметром идет имя нового элемента, вторым значение, которое задавать необязательно.
Добавим еще один шаг к инструкциям:
$node = $xml->instructions; // получаем ветвь инструкций $node->addChild('step', 'Почитать газету'); // добавляем элемент print_r($node);
Результат:
SimpleXMLElement Object ( [step] => Array ( [0] => Смешать все ингредиенты и тщательно замесить. [1] => Закрыть тканью и оставить на один час в тёплом помещении. [2] => Замесить ещё раз, положить на противень и поставить в духовку. [3] => Почитать газету ) )
Метод addAttribute() позволяет добавить атрибут к текущему узлу. Первый параметр это имя атрибута, второй значение.
$node = $xml->instructions; // получаем ветвь инструкций $step = $node->addChild('step', 'Почитать газету'); // добавляем элемент $step->addAttribute('newspaper', 'Аргументы и факты'); // добавляем артибут print_r($step);
Результат:
SimpleXMLElement Object ( [@attributes] => Array ( [newspaper] => Аргументы и факты ) [0] => Почитать газету )
Использование XPath
SimpleXML включает в себя встроенную поддержку XPath. Поиск всех элементов <step>:
foreach ($xml->xpath('//step') as $step) { echo $step . '<br/>'; }
Результат:
Смешать все ингредиенты и тщательно замесить.<br/> Закрыть тканью и оставить на один час в тёплом помещении.<br/> Замесить ещё раз, положить на противень и поставить в духовку.<br/>
Взаимодействие с DOM
PHP может преобразовывать XML узлы из SimpleXML в формат DOM и наоборот. Этот пример показывает, как можно изменить DOM элемент в SimpleXML:
$dom = new DOMDocument('1.0', 'utf-8'); $dom->load('recipe.xml'); $xml = simplexml_import_dom($dom);
Дополнительная информация
- Работа с XML средствами PHP
- Блог на Laravel 7, часть 17. Временная зона для пользователей, деплой на хостинг TimeWeb
- Блог на Laravel 7, часть 16. Роль нового пользователя, сообщение админу о новом посте
- Блог на Laravel 7, часть 15. Восстановление постов, slug для категории, поста и страницы
- Блог на Laravel 7, часть 14. Валидация данных и права доступа при загрузке изображений
- Блог на Laravel 7, часть 13. Загрузка и ресайз изображений для категорий и постов блога
- Блог на Laravel 7, часть 12. Доп.страницы сайта в панели управления и в публичной части
Поиск: PHP • Web-разработка • XML