Xml parser create: примеры (PHP)

Использование xml_parser_create для анализа XML в PHP
Раздел: XML
xml_parser_create(string encoding): resource

Основные сведения о функции xml_parser_create

Описание и назначение

Функция xml_parser_create создает и возвращает ресурс (объект XML Parser в PHP 8) XML-парсера для последующего использования. Этот парсер основан на библиотеке Expat, что позволяет анализировать XML-документы, но не проверять их на соответствие DTD. Используется для последовательного (SAX-подобного) чтения XML-данных.

Аргументы функции

Функция принимает один необязательный аргумент:

  • encoding (string) – задает кодировку символов для входных и выходных данных в XML-парсере. Если параметр опущен, кодировка определяется автоматически. Поддерживаемые кодировки: "ISO-8859-1", "UTF-8", "US-ASCII". Начиная с PHP 5, также поддерживается кодировка "ISO-10646-UCS-4" и другие.

Простые примеры использования

Создание парсера и разбор строки

Пример создания парсера с кодировкой UTF-8 и базовой обработкой.

<?php
$xml_string = "<note><to>Вася</to><from>Петя</from></note>";
$parser = xml_parser_create('UTF-8');

function startElement($parser, $name, $attrs) {
    echo "Начало тега: $name\n";
}

function endElement($parser, $name) {
    echo "Конец тега: $name\n";
}

function charData($parser, $data) {
    $data = trim($data);
    if ($data) echo "Данные: $data\n";
}

xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "charData");

if (!xml_parse($parser, $xml_string, true)) {
    die("Ошибка разбора: " . xml_error_string(xml_get_error_code($parser)));
}

xml_parser_free($parser);
?>
Начало тега: NOTE
Начало тега: TO
Данные: Вася
Конец тега: TO
Начало тега: FROM
Данные: Петя
Конец тега: FROM
Конец тега: NOTE
Парсер с автоматической кодировкой

Создание парсера без указания кодировки.

<?php
$parser = xml_parser_create();
$encoding = xml_parser_get_option($parser, XML_OPTION_TARGET_ENCODING);
echo "Кодировка парсера: $encoding\n";
xml_parser_free($parser);
?>
Кодировка парсера: UTF-8

Альтернативы в PHP

SimpleXML

Расширение SimpleXML предоставляет простой интерфейс для доступа к XML-данным, преобразуя элементы в объекты и атрибуты в свойства. Лучше подходит для работы с небольшими и структурированными XML-документами, когда необходим быстрый доступ к элементам по имени.

DOMDocument

Объектная модель документа (DOM) позволяет загружать, создавать и манипулировать XML-документами как древовидной структурой. Предпочтительнее для сложных операций: изменения структуры, валидации, XPath-запросов. Требует больше памяти, чем SAX-парсер.

Функция xml_parser_create оптимальна для последовательной обработки больших XML-файлов, когда нет необходимости загружать весь документ в память.

Аналоги в других языках

Python: xml.sax

Модуль SAX в Python реализует событийно-ориентированный парсинг, аналогичный Expat в PHP.

import xml.sax

class MyHandler(xml.sax.ContentHandler):
    def startElement(self, name, attrs):
        print(f"Начало: {name}")
    def characters(self, content):
        data = content.strip()
        if data: print(f"Данные: {data}")

parser = xml.sax.make_parser()
parser.setContentHandler(MyHandler())
parser.parse("data.xml")
JavaScript: DOMParser

В браузерном JavaScript для разбора XML часто используется DOMParser, который загружает весь документ в DOM-дерево. Для потокового парсинга можно использовать API, например, Streams API с TextDecoder.

const xmlString = `<note><to>Вася</to></note>`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
console.log(xmlDoc.getElementsByTagName("to")[0].textContent); // Вася
MySQL: ExtractValue

Функция ExtractValue() позволяет извлекать данные из XML-строки с помощью XPath-выражения. Работает только с фрагментами XML, хранящимися в столбцах.

SELECT ExtractValue('<note><to>Вася</to></note>', '/note/to') AS result;
result
Вася

Типичные ошибки

Отсутствие установленных обработчиков

Если не назначить обработчики элементов или данных, парсер не будет обрабатывать события.

<?php
$parser = xml_parser_create();
$xml = "<root>text</root>";
// Обработчики не установлены
xml_parse($parser, $xml, true); // Ничего не произойдет, ошибки не будет
?>
Неверная кодировка

Указание неподдерживаемой кодировки может привести к ошибке разбора.

<?php
$parser = xml_parser_create('WINDOWS-1251'); // Может вызвать проблемы
// Лучше конвертировать данные в UTF-8 до разбора
?>
Неосвобождение парсера

Забытый вызов xml_parser_free() может привести к утечкам памяти при массовой обработке.

<?php
for ($i = 0; $i < 10000; $i++) {
    $parser = xml_parser_create();
    // ... разбор ...
    // xml_parser_free($parser); // Утечка памяти без этой строки
}
?>

Изменения в новых версиях PHP

В PHP 8.0 функция xml_parser_create возвращает объект XMLParser вместо ресурса. Все связанные функции (например, xml_parse) были адаптированы для работы с этим объектом. Это изменение является частью общей инициативы по замене ресурсов на объекты.

Начиная с PHP 8.0.3, функция больше не принимает параметр кодировки типа NULL. Если передается NULL, он интерпретируется как пустая строка, что приводит к использованию кодировки по умолчанию (UTF-8).

Расширенные примеры

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

Пример извлечения атрибутов в обработчике начала элемента.

Пример php
<?php
$xml = '<book isbn="12345">Название книги</book>';
$parser = xml_parser_create();

function startTag($parser, $name, $attrs) {
    echo "Элемент: $name\n";
    foreach ($attrs as $key => $value) {
        echo "  Атрибут: $key = $value\n";
    }
}

xml_set_element_handler($parser, "startTag", null);
xml_parse($parser, $xml, true);
xml_parser_free($parser);
?>
Элемент: BOOK
  Атрибут: ISBN = 12345
Парсинг большого файла по частям

Чтение и обработка большого XML-файла без загрузки в память целиком.

Пример php
<?php
$parser = xml_parser_create();
xml_set_element_handler($parser, function($p, $name) {
    static $count = 0;
    if ($name == 'ITEM') $count++;
    if ($count % 1000 == 0) echo "Обработано элементов: $count\n";
}, null);

$fp = fopen('large_data.xml', 'r');
while ($data = fread($fp, 4096)) {
    if (!xml_parse($parser, $data, feof($fp))) {
        die("Ошибка строки: " . xml_get_current_line_number($parser));
    }
}
xml_parser_free($parser);
fclose($fp);
?>
Изменение опций парсера

Использование xml_parser_set_option для управления поведением парсера.

Пример php
<?php
$parser = xml_parser_create();
// Включение обработки пробелов как данных
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
// Установка кодировки результата
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
?>
Обработка пространств имен

Работа с XML, содержащим пространства имен.

Пример php
<?php
$xml = '<ns:root xmlns:ns="http://example.com">data</ns:root>';
$parser = xml_parser_create();
xml_set_element_handler($parser, function($parser, $name, $attrs) {
    echo "Полное имя тега: $name\n";
    // Имя включает префикс пространства имен
}, null);
xml_parse($parser, $xml, true);
?>
Полное имя тега: NS:ROOT

PHP xml_parser_create function comments

En
Xml parser create Create an XML parser