W3docs

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.

Практика

Практика
Что делает расширение SimpleXML в PHP?
Что делает расширение SimpleXML в PHP?
Was this page helpful?