W3docs

PHP SimpleXML

SimpleXML — встроенное расширение PHP для работы с XML-документами через удобный объектный интерфейс.

Введение

SimpleXML — встроенное расширение PHP, которое преобразует XML-документ в объект, доступный через обычный синтаксис свойств и массивов. Вместо того чтобы вручную обходить дерево узлов, вы пишете $xml->book->title — имена элементов становятся свойствами, а повторяющиеся элементы — итерируемыми списками.

Это делает SimpleXML самым быстрым способом прочитать файл конфигурации, обработать XML-ответ от API или создать небольшой XML-документ. На этой странице рассматривается загрузка XML, чтение элементов и атрибутов, работа с пространствами имён, запросы с помощью XPath, изменение документов и обработка ошибок синтаксического разбора.

SimpleXML лучше всего подходит для документов, которые без труда помещаются в памяти и имеют известную, достаточно плоскую структуру. Для очень больших файлов или низкоуровневого управления вам могут больше подойти PHP XML DOM или парсер XML на основе Expat.

Загрузка XML-документа

SimpleXMLElement можно создать из одного из трёх источников:

  • simplexml_load_string() — разбирает XML из строки (удобно для API-ответов).
  • simplexml_load_file() — разбирает XML из файла или URL.
  • new SimpleXMLElement($xml) — конструктор, который по умолчанию принимает строку.

Все три возвращают SimpleXMLElement, представляющий корневой элемент документа, а не обёртку вокруг всего файла. Поэтому если ваш корневой элемент — <library>, возвращённый объект и есть <library>.

<?php

$data = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<library>
    <book category="fiction">
        <title>The Hobbit</title>
        <author>J.R.R. Tolkien</author>
        <price>14.99</price>
    </book>
    <book category="science">
        <title>A Brief History of Time</title>
        <author>Stephen Hawking</author>
        <price>18.50</price>
    </book>
</library>
XML;

$library = simplexml_load_string($data);
echo get_class($library); // SimpleXMLElement

Чтение элементов и атрибутов

Дочерние элементы доступны как свойства. Когда элемент повторяется (например, <book>), свойство ведёт себя как список, по которому можно обращаться по индексу через [] или перебирать с помощью foreach. Атрибуты читаются через синтаксис доступа к массиву ($element['attr']).

<?php

$library = simplexml_load_string($data); // the XML from above

echo $library->book[0]->title . "\n";   // The Hobbit
echo count($library->book) . "\n";      // 2

foreach ($library->book as $book) {
    echo $book->title . " — " . $book['category'] . "\n";
}

Вывод:

The Hobbit
2
The Hobbit — fiction
A Brief History of Time — science

Важно: элемент, полученный таким образом, является объектом SimpleXMLElement, а не строкой. $book->price выводится как текст благодаря методу __toString(), но для арифметических операций или строгих сравнений сначала приведите его к нужному типу: (float) $book->price или (string) $book['category']. Забытое приведение типов — наиболее распространённая ошибка при работе с SimpleXML.

Запросы с помощью XPath

Для всего, что выходит за рамки простой навигации — фильтрации, поиска в глубине дерева, условной выборки — используйте xpath(). Он выполняет выражение XPath и возвращает массив совпадающих элементов.

<?php

$library = simplexml_load_string($data);

// Titles of books priced over 10
foreach ($library->xpath('//book[price>10]/title') as $title) {
    echo $title . "\n";
}
// The Hobbit
// A Brief History of Time

Работа с пространствами имён

Когда документ использует пространства имён XML, обратиться к элементам с префиксами через обычный доступ к свойствам не получится — необходимо вызвать children() (для элементов) или attributes() (для атрибутов) с URI пространства имён, либо зарегистрировать префикс перед выполнением XPath.

<?php

$rss = <<<XML
<rss xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <item>
            <title>Hello</title>
            <dc:creator>Jane Doe</dc:creator>
        </item>
    </channel>
</rss>
XML;

$xml = simplexml_load_string($rss);
$item = $xml->channel->item;

// Access the dc: namespace by URI
$dc = $item->children('http://purl.org/dc/elements/1.1/');
echo $dc->creator . "\n"; // Jane Doe

Изменение и создание XML

SimpleXML позволяет изменять существующие узлы, добавлять новые и сериализовать результат. Присвойте значение свойству, чтобы изменить его, вызовите addChild() для добавления элемента, а addAttribute() — для добавления атрибута. Метод asXML() возвращает документ в виде строки или записывает его в файл, если указан путь.

<?php

$book = simplexml_load_string('<book><title>Old Title</title><price>10.00</price></book>');

$book->title = 'New Title';            // change an existing value
$book->price = '12.50';
$book->addChild('author', 'Jane Doe'); // add a new element
$book->addAttribute('id', '42');       // add an attribute

echo $book->asXML();

Вывод:

<?xml version="1.0"?>
<book id="42"><title>New Title</title><price>12.50</price><author>Jane Doe</author></book>

Передача имени файла — $book->asXML('book.xml') — записывает документ на диск и возвращает true в случае успеха. Полное описание смотрите в asXML().

Обработка ошибок разбора

Если XML некорректен, функции загрузки возвращают false и генерируют предупреждения PHP. Чтобы перехватывать ошибки тихо и изучать их самостоятельно, включите внутреннюю обработку ошибок через libxml_use_internal_errors() и получите их с помощью libxml_get_errors().

<?php

libxml_use_internal_errors(true);

$broken = "<library><book><title>Unclosed</book></library>";
$xml = simplexml_load_string($broken);

if ($xml === false) {
    echo "Failed to parse XML:\n";
    foreach (libxml_get_errors() as $error) {
        echo trim($error->message) . "\n";
    }
    libxml_clear_errors();
}

Вывод:

Failed to parse XML:
Opening and ending tag mismatch: title line 1 and book
Opening and ending tag mismatch: book line 1 and library
Premature end of data in tag library line 1

Всегда проверяйте возвращаемое значение перед использованием результата — обращение к false как к объекту вызовет ошибки «attempt to read property on bool» в последующем коде.

Итоги

  • Загружайте XML с помощью simplexml_load_string(), simplexml_load_file() или new SimpleXMLElement(); возвращённый объект является корневым элементом.
  • Читайте дочерние элементы как свойства, а атрибуты — как ключи массива; приводите к (string), (int) или (float) перед сравнением или вычислениями.
  • Используйте xpath() для фильтрации и глубоких запросов, а children()/attributes() с URI — для документов с пространствами имён.
  • Изменяйте данные через присвоение свойств, addChild() и addAttribute(), затем сериализуйте с помощью asXML().
  • Защищайтесь от некорректных данных с помощью libxml_use_internal_errors() и libxml_get_errors().

Для более глубокого изучения смотрите Получение значений узлов с помощью SimpleXML, Обзор парсера SimpleXML и низкоуровневые функции libxml.

Практика

Практика
Что такое PHP SimpleXML?
Что такое PHP SimpleXML?
Was this page helpful?