xml_set_notation_decl_handler()
Функция xml_set_notation_decl_handler() регистрирует пользовательский обработчик объявлений нотаций в XML-парсере PHP.
Функция xml_set_notation_decl_handler() регистрирует пользовательский callback, который SAX-парсер (Expat) вызывает при каждом обнаружении объявления нотации в DTD документа. Она принадлежит расширению PHP xml и работает только с парсером, созданным через xml_parser_create() — на SimpleXML или DOM она не влияет.
Объявление нотации внутри <!DOCTYPE ...> выглядит следующим образом:
<!NOTATION png SYSTEM "image/png">Нотации именуют внешний формат данных (тип изображения, вспомогательную программу и т. д.), чтобы впоследствии на этот формат можно было ссылаться через непарсируемую сущность. В современном XML нотации встречаются редко, но если DTD их содержит, данный обработчик позволяет перехватывать, журналировать или проверять каждую из них во время разбора вместо молчаливого игнорирования.
Примечание: Расширение
xml(Expat) должно быть включено в вашей сборке PHP. Объявления нотаций появляются только внутри внутреннего или внешнего DTD, поэтому в документе без<!DOCTYPE>данный обработчик никогда не сработает.
Синтаксис
xml_set_notation_decl_handler(
XMLParser $parser,
callable|false $handler
): bool$parser— ресурс парсера, возвращённый функциейxml_parser_create()(илиxml_parser_create_ns()).$handler— callback, вызываемый для каждого объявления нотации, илиfalseдля удаления ранее установленного обработчика.
Функция возвращает true в случае успеха и false, если $parser не является допустимым парсером.
Сигнатура callback
Обработчик получает пять аргументов в строго определённом порядке:
function handler($parser, $notation_name, $base, $system_id, $public_id)| Параметр | Описание |
|---|---|
$parser | Парсер, инициировавший вызов обработчика. |
$notation_name | Имя нотации, например png. |
$base | Базовый URI для разрешения идентификаторов (обычно пустой). |
$system_id | Системный идентификатор (SYSTEM), или ""/null, если отсутствует. |
$public_id | Публичный идентификатор (PUBLIC), или ""/null, если отсутствует. |
Нотация может использовать SYSTEM (только системный идентификатор) или PUBLIC (публичный идентификатор и системный), поэтому перед использованием проверяйте, какие поля заполнены.
Пример: чтение объявлений нотаций
Следующий парсер выводит каждую найденную нотацию, включая формы SYSTEM и PUBLIC:
function handle_notation_decl($parser, $notation_name, $base, $system_id, $public_id) {
echo "Notation name: $notation_name\n";
echo " System ID: " . ($system_id ?? '(none)') . "\n";
echo " Public ID: " . ($public_id ?? '(none)') . "\n";
}
$xml_parser = xml_parser_create();
xml_set_notation_decl_handler($xml_parser, "handle_notation_decl");
$xml_data = <<<XML
<?xml version="1.0"?>
<!DOCTYPE root [
<!NOTATION png SYSTEM "image/png">
<!NOTATION gif PUBLIC "-//IETF//NOTATION GIF89a//EN" "http://www.w3.org/Graphics/GIF/spec-gif89a.txt">
]>
<root/>
XML;
if (!xml_parse($xml_parser, $xml_data, true)) {
echo "XML error: " . xml_error_string(xml_get_error_code($xml_parser)) . "\n";
}
xml_parser_free($xml_parser);Результат выполнения:
Notation name: png
System ID: image/png
Public ID: (none)
Notation name: gif
System ID: http://www.w3.org/Graphics/GIF/spec-gif89a.txt
Public ID: -//IETF//NOTATION GIF89a//ENОбратите внимание: для нотации SYSTEM задан только системный идентификатор, тогда как для нотации PUBLIC заполнены оба идентификатора. Третий аргумент true в функции xml_parse() означает, что данные являются финальным фрагментом, а xml_parser_free() освобождает парсер по завершении работы.
Распространённые ошибки
- Нет DTD — нет callback. Обработчик срабатывает только для объявлений
<!NOTATION>, которые находятся внутри<!DOCTYPE>. В обычном документе без DOCTYPE он никогда не вызывается. - Регистрируйте до начала разбора. Устанавливайте обработчик до первого вызова
xml_parse(); объявления сообщаются по мере чтения парсером DTD. - Используйте метод класса как callback. Передавайте
[$object, 'method'](или привяжите с помощьюxml_set_object()), если обработчик является методом класса. - Сочетайте с непарсируемыми сущностями. Нотации обычно указываются в сущностях
NDATA— обрабатывайте их с помощьюxml_set_unparsed_entity_decl_handler().
Связанные обработчики
xml_set_notation_decl_handler() — один из нескольких SAX-callback, которые можно подключить к одному парсеру:
xml_set_element_handler()— открывающие и закрывающие теги.xml_set_character_data_handler()— текстовое содержимое.xml_set_unparsed_entity_decl_handler()— непарсируемые (NDATA) сущности.xml_set_default_handler()— всё, для чего не задан специальный обработчик.
Заключение
xml_set_notation_decl_handler() позволяет перехватывать объявления <!NOTATION> в процессе SAX-разбора вместо их игнорирования. Зарегистрируйте callback с пятью аргументами до начала разбора, изучите получаемые системный и публичный идентификаторы и комбинируйте функцию с другими обработчиками xml_set_* для полноценной обработки документа с DTD. Для более широкого контекста смотрите главу PHP XML Parser.