xml_set_unparsed_entity_decl_handler()
Функция xml_set_unparsed_entity_decl_handler() в PHP устанавливает пользовательский обработчик для необработанных объявлений сущностей в XML
Функция xml_set_unparsed_entity_decl_handler() устанавливает пользовательский callback-обработчик для необработанных объявлений сущностей в XML-парсере. Она входит в расширение XML Parser (SAX) PHP и принадлежит к тому же семейству функций, что xml_set_element_handler() и xml_set_character_data_handler() — она не применима к SimpleXML или DOM.
Необработанная сущность — это сущность, содержимое которой XML-процессор не должен разбирать как XML. Как правило, это ссылка на внешние двоичные данные: изображение, PDF или аудиофайл. Такие сущности объявляются с ключевым словом NDATA и именем нотации, например:
<!ENTITY logo SYSTEM "logo.png" NDATA png>Когда парсер встречает подобное объявление в DTD документа, он вызывает ваш обработчик, чтобы вы могли зафиксировать расположение ресурса, не пытаясь загрузить его как разметку.
Синтаксис
xml_set_unparsed_entity_decl_handler(
XMLParser $parser,
callable $handler
): true| Параметр | Описание |
|---|---|
$parser | XML-парсер, созданный с помощью xml_parser_create(). |
$handler | Callable-значение или строковое имя функции. Передайте пустую строку ("") для удаления текущего обработчика. |
Возвращаемое значение: всегда возвращает true.
Примечание о PHP 8: начиная с PHP 8.0 парсер является объектом
XMLParser, а неresource, однако код пишется одинаково — продолжайте обращаться со значением, возвращаемымxml_parser_create(), как с непрозрачным дескриптором.
Сигнатура callback-функции
Ваш обработчик вызывается с шестью аргументами в следующем порядке:
handler(
XMLParser $parser,
string $entityName, // e.g. "logo"
string $base, // base URI used to resolve the system id (often empty)
string $systemId, // e.g. "logo.png"
string $publicId, // public id, if any
string $notationName // e.g. "png" — declared with xml_set_notation_decl_handler()
): voidПример: перехват объявлений необработанных сущностей
Создайте SAX-парсер с помощью xml_parser_create(), зарегистрируйте обработчик, затем передайте XML в xml_parse():
<?php
function handleUnparsedEntity($parser, $name, $base, $systemId, $publicId, $notationName) {
echo "Unparsed entity '$name' -> $systemId (notation: $notationName)\n";
}
$xmlParser = xml_parser_create();
xml_set_unparsed_entity_decl_handler($xmlParser, "handleUnparsedEntity");
$xml = '<?xml version="1.0"?>
<!DOCTYPE catalog [
<!NOTATION png SYSTEM "image/png">
<!ENTITY logo SYSTEM "logo.png" NDATA png>
<!ENTITY manual SYSTEM "manual.pdf" NDATA pdf>
]>
<catalog/>';
xml_parse($xmlParser, $xml, true);
xml_parser_free($xmlParser);Ожидаемый вывод:
Unparsed entity 'logo' -> logo.png (notation: png)
Unparsed entity 'manual' -> manual.pdf (notation: pdf)Обработчик вызывается один раз для каждой сущности NDATA в DTD, предоставляя путь к файлу ($systemId) и нотацию. В реальном приложении эти ссылки сохраняются — например, для последующей загрузки ресурсов — а не выводятся в консоль.
Типичные ошибки
- DTD должен содержать объявления
NDATA. Обычная внутренняя сущность (<!ENTITY name "value">) является разбираемым текстом, поэтому данный обработчик её не видит. Только сущности, помеченныеNDATA notation, являются «необработанными». - Регистрируйте обработчики до вызова
xml_parse(). Как и все функцииxml_set_*_handler(), эта не имеет никакого эффекта после начала разбора. - Освобождайте парсер с помощью
xml_parser_free()по завершении работы, чтобы освободить ресурсы. - Не применяется в SimpleXML. Если вы читаете корректно сформированный XML и не нуждаетесь в реакции на объявления сущностей DTD, более простой парсер SimpleXML обычно является лучшим выбором.
Связанные функции
xml_parser_create()— создаёт SAX-парсер, к которому привязывается данный обработчик.xml_set_notation_decl_handler()— обрабатывает объявления<!NOTATION ...>, на которые ссылаются необработанные сущности.xml_set_external_entity_ref_handler()— обрабатывает ссылки на разбираемые внешние сущности.xml_set_element_handler()— обрабатывает события начала и окончания элементов.
Заключение
xml_set_unparsed_entity_decl_handler() позволяет SAX-парсеру уведомлять вас о сущностях NDATA — ссылках на внешние двоичные данные — чтобы вы могли зафиксировать пути и нотации, не пытаясь разобрать их как XML. Регистрируйте обработчик до вызова xml_parse(), ожидайте callback с шестью аргументами и помните, что функция применяется только к процедурному расширению XML Parser, а не к SimpleXML или DOM.