addChild()
Метод PHP SimpleXMLElement::addChild() — добавление дочерних элементов в XML-документ: значения, пространства имён, подводные камни и примеры.
Введение
SimpleXMLElement::addChild() — это метод для построения XML с нуля в PHP, узел за узлом. SimpleXML — встроенное расширение PHP, которое превращает XML-документ в объект, с которым можно работать с помощью обычного синтаксиса свойств. Если чтение данных выглядит так просто, как $xml->book->title, то создание нового элемента — это задача addChild().
На этой странице рассказывается, что возвращает addChild() и почему это важно, как добавлять значения и пространства имён, а также какие подводные камни встречаются чаще всего (экранирование сущностей, атрибуты и элементы, ловушка со значением null). Все примеры ниже можно запустить.
Синтаксис
public SimpleXMLElement::addChild(
string $qualifiedName,
?string $value = null,
?string $namespace = null
): ?SimpleXMLElement$qualifiedName— имя (тег) нового дочернего элемента, например"title".$value— необязательное текстовое содержимое элемента. Если параметр опущен или равенnull, создаётся пустой элемент (<title/>).$namespace— необязательный URI пространства имён, к которому принадлежит дочерний элемент.
Возвращаемое значение — ключевая деталь: addChild() возвращает только что созданный дочерний элемент, а не родительский. Именно на этот возвращённый объект нужно навешивать дальнейшие вызовы, чтобы строить вложенные структуры.
Добавление одного дочернего элемента
Результат:
<?xml version="1.0"?>
<books><book>PHP Basics</book></books>Мы начинаем с корневого элемента <books>, затем добавляем один дочерний элемент <book> с текстовым содержимым PHP Basics. Метод asXML() сериализует объект обратно в XML-строку.
Построение вложенной структуры
Поскольку addChild() возвращает только что созданный дочерний элемент, нужно сохранить это возвращаемое значение, чтобы добавлять более глубокие уровни:
<?php
$xml = new SimpleXMLElement('<books></books>');
$book = $xml->addChild('book'); // returns the <book> element
$book->addChild('title', 'PHP Basics'); // adds <title> inside <book>
$book->addChild('author', 'John Doe'); // adds <author> inside <book>
echo $xml->asXML();Вывод:
<?xml version="1.0"?>
<books><book><title>PHP Basics</title><author>John Doe</author></book></books>Если бы вместо $book->addChild(...) вы вызвали $xml->addChild('title', ...), элемент <title> оказался бы рядом с <book>, а не внутри него. Объект, на котором вызывается addChild(), всегда является родительским.
Дочерние элементы и атрибуты
addChild() создаёт только элементы. Чтобы добавить атрибут (например, id="1"), воспользуйтесь методом addAttribute() на том же элементе:
<?php
$xml = new SimpleXMLElement('<books></books>');
$book = $xml->addChild('book');
$book->addAttribute('id', '1');
$book->addChild('title', 'PHP Basics');
echo $xml->asXML();Вывод:
<?xml version="1.0"?>
<books><book id="1"><title>PHP Basics</title></book></books>Специальные символы: реальная ловушка
Можно ожидать, что addChild() сам экранирует небезопасные для XML символы в значении. Однако это не так — передача сырого & заставляет SimpleXML воспринять его как начало ссылки на сущность, что вызывает предупреждение "unterminated entity reference" и потерю содержимого:
<?php
$xml = new SimpleXMLElement('<docs></docs>');
$xml->addChild('note', 'Tom & Jerry <fun>'); // Warning: unterminated entity reference
echo $xml->asXML();В результате выводится пустой элемент, а не ожидаемый текст:
<?xml version="1.0"?>
<docs><note/></docs>Надёжный способ задать текст, содержащий &, < или >, — это присвоение через свойство, которое выполняет корректное экранирование:
<?php
$xml = new SimpleXMLElement('<docs></docs>');
$xml->note = 'Tom & Jerry <fun>';
echo $xml->asXML();Вывод:
<?xml version="1.0"?>
<docs><note>Tom & Jerry <fun></note></docs>Итак: используйте addChild() для создания элемента, но присваивайте ненадёжный текст или текст со специальными символами через свойство (либо заранее экранируйте с помощью htmlspecialchars()).
Добавление дочерних элементов с пространством имён
Третий аргумент связывает дочерний элемент с URI пространства имён:
<?php
$xml = new SimpleXMLElement('<feed xmlns:dc="http://purl.org/dc/elements/1.1/"></feed>');
$xml->addChild('creator', 'Jane Roe', 'http://purl.org/dc/elements/1.1/');
echo $xml->asXML();Вывод:
<?xml version="1.0"?>
<feed xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:creator>Jane Roe</dc:creator></feed>Распространённые ловушки
- Не игнорируйте возвращаемое значение при вложении.
addChild()возвращает новый дочерний элемент; продолжайте работу именно с ним, а не с корнем, иначе элементы окажутся на одном уровне. nullи пустая строка. ВызовыaddChild('tag')иaddChild('tag', null)создают пустой самозакрывающийся элемент (<tag/>). Передайте'', чтобы получить пустой, но присутствующий текстовый узел.- Значения не экранируются безопасно. Сырой
&в значении вызывает предупреждение о ссылке на сущность и потерю текста; присваивайте содержимое со специальными символами через свойство ($el->tag = $text;) или заранее экранируйте его. Имена элементов должны быть допустимыми XML-идентификаторами. - Метод изменяет документ на месте.
addChild()модифицирует документ, обёрнутый объектом; никакого отдельного шага «сохранения» нет — достаточно сериализовать с помощьюasXML().
Когда использовать
Используйте addChild(), когда нужно генерировать XML — создавать RSS/Atom-ленту, карту сайта, конфигурационный файл или полезную нагрузку API — и вам нравится лёгкий объектный синтаксис SimpleXML. Для разбора существующего XML обычно начинают с simplexml_load_string() или simplexml_load_file(), а затем читают данные с помощью children(). Для документов, требующих сложного редактирования (перемещения или удаления узлов), лучше подходит расширение DOM.
Заключение
SimpleXMLElement::addChild() добавляет дочерний элемент к XML-узлу и возвращает этот новый дочерний элемент, позволяя плавно строить вложенные деревья. Запомните главное: метод возвращает дочерний элемент, сырые специальные символы в значении требуют присвоения через свойство или предварительного экранирования, атрибуты добавляются через addAttribute(), а необязательный третий аргумент помещает дочерний элемент в пространство имён. Обратитесь к разделу PHP SimpleXML для более широкого понимания работы с XML в PHP.