Xml set end namespace decl handler: примеры (PHP)

Обработка завершения пространств имен XML в PHP
Раздел: XML
xml_set_end_namespace_decl_handler(resource parser, callable handler): bool

Описание функции xml_set_end_namespace_decl_handler

Функция xml_set_end_namespace_decl_handler устанавливает обработчик, который вызывается парсером XML при завершении объявления пространства имен. Она используется в расширении XML Parser для обработки событий парсинга XML-документов с поддержкой пространств имен.

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

Функция принимает два аргумента:

  1. parser - ресурсный указатель на XML-парсер, созданный функцией xml_parser_create_ns().
  2. handler - имя функции обратного вызова (callback), которая будет вызываться при завершении объявления пространства имен.
Специфика работы

Обработчик вызывается, когда парсер достигает конца объявления пространства имен (например, закрывающего тега элемента, в котором было объявлено пространство). Функция работает только с парсерами, созданными с помощью xml_parser_create_ns(), так как они поддерживают пространства имен.

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

Простой пример с одним пространством имен

Код устанавливает обработчик для завершения объявления пространства имен.

<?php
function endNamespaceHandler($parser, $prefix) {
    echo "Завершение пространства имен с префиксом: $prefix\n";
}

$xml = '<root xmlns:book="http://example.com/books"><book:title>PHP Guide</book:title></root>';
$parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($parser, 'endNamespaceHandler');
xml_parse($parser, $xml, true);
xml_parser_free($parser);
?>
Завершение пространства имен с префиксом: book
Пример с несколькими пространствами имен
<?php
function endNamespace($parser, $prefix) {
    if ($prefix === '') {
        echo "Завершение пространства имен по умолчанию\n";
    } else {
        echo "Завершение пространства имен: $prefix\n";
    }
}

$xml = '<catalog xmlns="http://example.com" xmlns:auth="http://example.com/authors">';
$xml .= '<book auth:id="123">Пример</book></catalog>';
$parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($parser, 'endNamespace');
xml_parse($parser, $xml, true);
xml_parser_free($parser);
?>
Завершение пространства имен по умолчанию
Завершение пространства имен: auth

Похожие функции в PHP

Для обработки XML в PHP существуют другие функции и расширения:

  • xml_set_start_namespace_decl_handler - устанавливает обработчик начала объявления пространства имен. Используется вместе с xml_set_end_namespace_decl_handler для полного отслеживания областей видимости пространств имен.
  • SimpleXML - расширение для простого доступа и управления XML-данными. Предпочтительно для чтения и простых преобразований XML без низкоуровневого контроля.
  • DOMDocument - объектно-ориентированный API для работы с XML/HTML. Рекомендуется для сложных операций, таких как валидация, манипуляция структурой или XPath-запросы.
  • XMLReader - последовательный парсер для больших XML-файлов с низким потреблением памяти. Подходит для потоковой обработки данных.

Функции XML Parser, включая xml_set_end_namespace_decl_handler, полезны для событийно-ориентированного парсинга с полным контролем над процессом.

Альтернативы в других языках программирования

Xml set end namespace decl handler в Python

В модуле xml.sax используется аналогичный событийный подход. Обработчик endPrefixMapping соответствует xml_set_end_namespace_decl_handler.

import xml.sax

class NamespaceHandler(xml.sax.ContentHandler):
    def endPrefixMapping(self, prefix):
        print(f"Завершение пространства имен: {prefix}")

parser = xml.sax.make_parser()
handler = NamespaceHandler()
parser.setContentHandler(handler)
parser.parseString('<root xmlns:test="urn:test"><test:node/></root>')
Завершение пространства имен: test
JavaScript (Node.js)

В библиотеке sax.js есть событие endPrefixMapping для обработки завершения пространства имен.

const sax = require('sax');
const parser = sax.parser(true);
parser.on('endPrefixMapping', (prefix) => {
    console.log(`Завершение пространства имен: ${prefix}`);
});
parser.write('<doc xmlns:ns="http://example.com"><ns:el/></doc>');
parser.close();
Завершение пространства имен: ns
Отличия от PHP

В Python и JavaScript обработчики являются методами классов или функциями в событийной модели, тогда как в PHP требуется явная установка callback-функции. PHP-функция работает только с парсером, созданным специально для пространств имен.

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

Использование неподходящего парсера

Функция требует парсер, созданный через xml_parser_create_ns(). Использование парсера от xml_parser_create() приводит к неработоспособности.

<?php
function handler($parser, $prefix) {}
$parser = xml_parser_create(); // Парсер без поддержки пространств имен
xml_set_end_namespace_decl_handler($parser, 'handler');
?>
Warning: xml_set_end_namespace_decl_handler(): Unable to call handler
Некорректное имя обработчика

Передача несуществующей функции в качестве обработчика вызывает ошибку.

<?php
$parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($parser, 'undefined_function');
?>
Warning: xml_set_end_namespace_decl_handler(): Unable to call handler
Неверное количество аргументов в обработчике

Обработчик должен принимать ровно два аргумента.

<?php
function handler($parser) { // Пропущен второй аргумент
    echo "Обработчик";
}
$parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($parser, 'handler');
xml_parse($parser, '<root xmlns:a="urn:a"/>', true);
?>
Warning: handler() expects exactly 2 parameters, 1 given

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

Функция xml_set_end_namespace_decl_handler оставалась стабильной в основных версиях PHP. Однако в PHP 8.0.0 расширение XML Parser было переведено в режим долгосрочной поддержки, без значительных изменений в работе функции.

  • В PHP 8.0.0 тип параметра parser изменен с ресурса (resource) на объект XMLParser.
  • Вызов функции с некорректным количеством аргументов теперь вызывает исключение ArgumentCountError.
  • Прекращена поддержка Windows-кодировок по умолчанию, требуется явное указание кодировки.

Рекомендуется использовать современные альтернативы, такие как DOM или SimpleXML, для новых проектов, так как XML Parser считается устаревшим.

Расширенные примеры использования

Отслеживание вложенных пространств имен

Пример демонстрирует обработку завершения пространств имен во вложенных элементах.

Пример php
<?php
$log = [];
function endNs($parser, $prefix) {
    global $log;
    $log[] = "Завершено: " . ($prefix ?: '(по умолчанию)');
}

$xml = '<a xmlns:x="urn:x">';
$xml .= '<b xmlns:y="urn:y"><c/></b>';
$xml .= '<d/></a>';

$parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($parser, 'endNs');
xml_parse($parser, $xml, true);
xml_parser_free($parser);

print_r($log);
?>
Array
(
    [0] => Завершено: y
    [1] => Завершено: x
)
Интеграция с другими обработчиками

Использование совместно с обработчиками начала пространств имен и элементов для полного контроля.

Пример php
<?php
function startElement($parser, $name, $attrs) {
    $parts = explode(':', $name);
    if (count($parts) > 1) {
        echo "Начало элемента с префиксом: {$parts[0]}\n";
    }
}

function startNamespace($parser, $prefix, $uri) {
    echo "Начало пространства имен: $prefix ($uri)\n";
}

function endNamespace($parser, $prefix) {
    echo "Завершение пространства имен: $prefix\n";
}

$parser = xml_parser_create_ns();
xml_set_element_handler($parser, 'startElement', null);
xml_set_start_namespace_decl_handler($parser, 'startNamespace');
xml_set_end_namespace_decl_handler($parser, 'endNamespace');

$xml = '<root xmlns:doc="http://doc.example"><doc:page>Текст</doc:page></root>';
xml_parse($parser, $xml, true);
xml_parser_free($parser);
?>
Начало пространства имен: doc (http://doc.example)
Начало элемента с префиксом: doc
Завершение пространства имен: doc
Сбор информации о пространствах имен

Пример сбора данных о времени жизни пространств имен в документе.

Пример php
<?php
$namespaces = [];

function startNs($parser, $prefix, $uri) {
    global $namespaces;
    $namespaces[$prefix ?: '(default)'] = ['uri' => $uri, 'active' => true];
}

function endNs($parser, $prefix) {
    global $namespaces;
    $key = $prefix ?: '(default)';
    if (isset($namespaces[$key])) {
        $namespaces[$key]['active'] = false;
        echo "Пространство имен $key стало неактивным\n";
    }
}

$parser = xml_parser_create_ns('UTF-8');
xml_set_start_namespace_decl_handler($parser, 'startNs');
xml_set_end_namespace_decl_handler($parser, 'endNs');

$xml = '<r xmlns:a="urn:a"><c xmlns:b="urn:b"/><d/></r>';
xml_parse($parser, $xml, true);
xml_parser_free($parser);

print_r($namespaces);
?>
Пространство имен b стало неактивным
Пространство имен a стало неактивным
Array
(
    [a] => Array
        (
            [uri] => urn:a
            [active] =>
        )
    [b] => Array
        (
            [uri] => urn:b
            [active] =>
        )
)

PHP xml_set_end_namespace_decl_handler function comments

En
Xml set end namespace decl handler Set up end namespace declaration handler