SimpleXML в PHP: Подробное руководство
SimpleXML — мощный инструмент PHP для разбора и обработки XML-данных. Узнайте, как использовать SimpleXML в PHP с примерами.
SimpleXML — это встроенное расширение PHP, которое преобразует XML-документ в дерево объектов, доступных для чтения, перебора и изменения с помощью обычного синтаксиса PHP. В этом руководстве рассматривается загрузка XML, чтение элементов и атрибутов, работа с пространствами имён, изменение узлов и сохранение результата — с исполняемыми примерами и типичными ловушками.
Введение в SimpleXML
SimpleXML — это расширение PHP, позволяющее разбирать и изменять XML-данные с минимальным количеством кода. Оно отличается от расширения DOM, однако оба построены поверх одной библиотеки libxml2, поэтому используют общий механизм обработки ошибок. Компромисс прост:
- SimpleXML — лучший выбор для чтения правильно оформленного XML, когда нужно просто обойти известную структуру. Краткий, объектно-подобный доступ.
- DOM — предпочтительнее при активном редактировании, перемещении узлов или когда требуется полный контроль над деревом документа.
SimpleXML включён по умолчанию в стандартных сборках PHP, поэтому обычно ничего устанавливать не нужно.
Загрузка XML
Существует две точки входа. Используйте simplexml_load_file() для файла или URL, а simplexml_load_string() — для XML, уже имеющегося в виде строки (например, ответа API).
Поскольку обе функции опираются на libxml2, некорректный документ вызывает предупреждения PHP и возвращает false. Всегда сначала переключайтесь на внутреннюю обработку ошибок с помощью libxml_use_internal_errors(), чтобы самостоятельно анализировать ошибки вместо вывода предупреждений в поток вывода:
Загрузка XML-файла
libxml_use_internal_errors(true);
$xml = simplexml_load_file('data.xml');
if ($xml === false) {
foreach (libxml_get_errors() as $error) {
echo trim($error->message), PHP_EOL;
}
die('Failed to load XML.');
}simplexml_load_string() работает аналогично, но принимает текст XML напрямую:
Загрузка XML из строки
$source = '<data><item><name>John Doe</name></item></data>';
$xml = simplexml_load_string($source);В обоих случаях возвращаемое значение — это SimpleXMLElement, представляющий корневой элемент документа.
Доступ к элементам
SimpleXML сопоставляет каждый дочерний элемент со свойством родительского объекта, к которому обращаются через оператор -> (не через точку — в PHP нет доступа к членам через .). К повторяющимся дочерним элементам обращаются по индексу. Рассмотрим такой XML:
Пример XML
<data>
<item>
<name>John Doe</name>
<age>30</age>
</item>
<item>
<name>Jane Doe</name>
<age>28</age>
</item>
</data>Читаем первый элемент, затем перебираем все item с помощью foreach:
Получение значений элементов
// The first <item> (index 0)
$name = $xml->item[0]->name;
$age = $xml->item[0]->age;
// Iterate through all <item> elements
foreach ($xml->item as $item) {
echo $item->name . ' is ' . $item->age . ' years old.' . PHP_EOL;
}Ловушка с приведением к строке
$item->name — не строка, а SimpleXMLElement. Она лишь выглядит как строка при выводе через echo, поскольку элемент автоматически приводится в строковых контекстах. Если вы сохраняете значение в массив, передаёте его в json_encode() или сравниваете строго, сначала явно приведите его:
$name = (string) $xml->item[0]->name; // plain string
$age = (int) $xml->item[0]->age; // plain intЧтение атрибутов
Атрибуты элемента доступны через синтаксис массива, а не через оператор ->. Для <item id="1" status="active"> обращаемся так:
Доступ к атрибутам
$id = (string) $xml->item[0]['id']; // "1"
$status = (string) $xml->item[0]['status']; // "active"
// Loop over every attribute on an element
foreach ($xml->item[0]->attributes() as $key => $value) {
echo "$key = $value" . PHP_EOL;
}Работа с пространствами имён
XML с пространствами имён (префиксы вида <atom:link>) не разрешается через обычный доступ к свойствам — необходимо зарегистрировать пространство имён с помощью children() или использовать XPath-запрос. Именно это чаще всего является причиной того, что «элемент пустой», хотя он явно присутствует в файле:
Элементы с пространствами имён
$source = '<feed xmlns:atom="http://www.w3.org/2005/Atom">'
. '<atom:title>Hello</atom:title></feed>';
$xml = simplexml_load_string($source);
$atom = $xml->children('http://www.w3.org/2005/Atom');
echo (string) $atom->title; // "Hello"Запросы с XPath
Для всего, что глубже прямого дочернего элемента, xpath() возвращает массив совпадающих элементов — это намного чище, чем вложенные циклы:
// Every <name> anywhere under the root
foreach ($xml->xpath('//name') as $name) {
echo (string) $name . PHP_EOL;
}Изменение и добавление элементов
Значение можно изменить, присвоив его свойству, а расширить дерево можно с помощью addChild() / addAttribute():
Изменение и создание узлов
// Change existing values
$xml->item[0]->name = 'John Smith';
$xml->item[0]->age = 32;
// Add a brand-new child element and an attribute
$new = $xml->addChild('item');
$new->addChild('name', 'New Person');
$new->addAttribute('id', '99');Присвоение значения заменяет текстовое содержимое элемента; addChild() добавляет новый элемент, а не перезаписывает существующий.
Преобразование обратно в XML
Используйте метод asXML() для сериализации (возможно, изменённого) дерева обратно в строку, а затем запишите её с помощью file_put_contents():
Сохранение изменений обратно в XML
file_put_contents('data.xml', $xml->asXML());Вызванный без аргументов, asXML() возвращает полный документ в виде строки вместе с объявлением <?xml version="1.0"?> — именно то, что нужно для сохранения. Вызовите метод на дочернем элементе ($xml->item[0]->asXML()), чтобы получить только этот фрагмент без объявления.
Заключение
SimpleXML — это самый быстрый способ читать и слегка редактировать правильно оформленный XML в PHP: загружайте с помощью simplexml_load_file() или simplexml_load_string(), обходите дерево через -> и индексирование массива, читайте атрибуты через [] и сериализуйте обратно с asXML(). Помните о двух повторяющихся ловушках — приводите элементы к строкам перед повторным использованием и регистрируйте пространства имён перед обращением к узлам с префиксами. Для программного масштабного редактирования документов обращайтесь к расширению DOM. Чтобы углубиться в тему, продолжайте с PHP SimpleXML и чтением данных с помощью SimpleXML get.