Xml parser create: примеры (PHP)
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 предоставляет простой интерфейс для доступа к XML-данным, преобразуя элементы в объекты и атрибуты в свойства. Лучше подходит для работы с небольшими и структурированными XML-документами, когда необходим быстрый доступ к элементам по имени.
Объектная модель документа (DOM) позволяет загружать, создавать и манипулировать XML-документами как древовидной структурой. Предпочтительнее для сложных операций: изменения структуры, валидации, XPath-запросов. Требует больше памяти, чем SAX-парсер.
Функция xml_parser_create оптимальна для последовательной обработки больших XML-файлов, когда нет необходимости загружать весь документ в память.
Аналоги в других языках
Модуль 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 для разбора 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); // ВасяФункция 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
$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
$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
$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
$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