W3docs

xml_set_end_namespace_decl_handler()

The xml_set_end_namespace_decl_handler() function is a PHP built-in function that sets a user-defined function as the handler for end namespace declarations in

The xml_set_end_namespace_decl_handler() function is a PHP built-in function that registers a user-defined callback to run whenever the SAX XML parser reaches the end of an element that declared one or more XML namespaces. It is the closing counterpart of xml_set_start_namespace_decl_handler(): the start handler fires when a namespace prefix comes into scope, and this end handler fires when that prefix goes back out of scope.

This function belongs to PHP's event-driven (SAX) xml extension, which reads a document top to bottom and calls your handlers as it encounters each construct, rather than building a tree in memory like SimpleXML. It is most useful when you want to track which namespaces are currently active while parsing — for example, to maintain a stack of in-scope prefixes or to clean up state once a namespaced section ends.

When to use it

A namespace declaration is an attribute such as xmlns:ns="http://example.com". Its scope is the element it appears on and all of that element's descendants. Use the end-namespace handler when you need to know the exact moment that scope closes — typically to pop a prefix off a stack you built in the start handler, mirroring how the parser itself manages scope.

Syntax

xml_set_end_namespace_decl_handler(XMLParser $parser, callable|false $handler): bool
ParameterDescription
$parserThe XML parser, created by xml_parser_create_ns() (recommended) or xml_parser_create().
$handlerThe callback to run on each end-of-namespace event, or false to remove a previously set handler.

Return value: returns true on success and false on failure (for example, if $parser is not a valid parser).

Your handler receives two arguments:

function handler(XMLParser $parser, string $prefix): void

$prefix is the namespace prefix whose scope is ending (an empty string "" for a default xmlns="..." declaration). Note that, unlike the start handler, the end handler does not receive the namespace URI — only the prefix.

Usage Examples

Example: Setting an end namespace declaration handler

This example sets up the handler and triggers it by parsing a small XML string. The handler is invoked during xml_parse(), as the parser closes the element that declared the namespace.

Parsing XML with an end namespace declaration handler

function handle_end_namespace_decl($parser, $prefix) {
    echo "End of namespace prefix: $prefix\n";
}

$xml_parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($xml_parser, "handle_end_namespace_decl");

$xml_data = '<?xml version="1.0"?><root xmlns:ns="http://example.com"><ns:child/></root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);

The ns prefix is declared on <root>, so its scope ends when </root> is reached. When the handler fires, it prints the prefix going out of scope:

End of namespace prefix: ns

Heads up: firing of the end namespace handler is sensitive to the underlying libexpat/PHP build — on some PHP versions the start handler runs while the end handler does not. Always test against your target runtime, and never rely on the end handler alone to detect a namespace; pair it with the start handler (below) so your state stays consistent.

Example: Pairing start and end handlers to track scope

In real parsers the end handler is rarely used alone. Pairing it with the start handler lets you maintain a stack of the prefixes currently in scope. The start handler pushes each prefix as it comes into scope; the end handler pops it when the declaring element closes:

Tracking in-scope namespace prefixes with a stack

$activePrefixes = [];

function on_start_ns($parser, $prefix, $uri) {
    global $activePrefixes;
    $activePrefixes[] = $prefix;
    echo "Enter '$prefix' -> $uri | active: " . implode(', ', $activePrefixes) . "\n";
}

function on_end_ns($parser, $prefix) {
    global $activePrefixes;
    array_pop($activePrefixes);
    echo "Leave '$prefix' | active: " . implode(', ', $activePrefixes) . "\n";
}

$parser = xml_parser_create_ns();
xml_set_start_namespace_decl_handler($parser, "on_start_ns");
xml_set_end_namespace_decl_handler($parser, "on_end_ns");

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

xml_parse($parser, $xml, true);
xml_parser_free($parser);

The x prefix is declared on <a> and y on the inner <b>. As scopes open and close, the stack tracks which prefixes are currently active. The end events fire in last-in, first-out order — y (the inner one) leaves scope before x:

Enter 'x' -> urn:x | active: x
Enter 'y' -> urn:y | active: x, y
Leave 'y' | active: x
Leave 'x' | active: 

This start/pop pattern is the canonical use of the end handler: it keeps your view of in-scope namespaces aligned with the parser's own scope management.

Common gotchas

  • Use xml_parser_create_ns(). Namespace handlers only receive events when the parser is namespace-aware. A parser made with the plain xml_parser_create() will not split prefixes from URIs.
  • No URI in the end callback. If you need the URI when scope closes, capture it in the start handler (keyed by prefix) and look it up here.
  • Set handlers before parsing. Register the handler before the first call to xml_parse(); handlers set mid-parse will miss earlier events.
  • Free the parser. Call xml_parser_free() when done to release resources, especially in long-running scripts.

Conclusion

xml_set_end_namespace_decl_handler() lets a SAX parser tell your code exactly when an XML namespace prefix goes out of scope. Combined with xml_set_start_namespace_decl_handler() and a namespace-aware parser from xml_parser_create_ns(), it gives you precise, low-memory control over namespace scope while streaming through large XML documents.

Practice

Practice
What is the function of xml_set_end_namespace_decl_handler() in PHP?
What is the function of xml_set_end_namespace_decl_handler() in PHP?
Was this page helpful?