xml_set_start_namespace_decl_handler()
The xml_set_start_namespace_decl_handler() function is a PHP built-in function that sets a user-defined function as the handler for start namespace declarations
The xml_set_start_namespace_decl_handler() function registers a callback that the XML parser invokes each time it encounters the start of a namespace declaration — that is, an xmlns or xmlns:prefix attribute that brings a namespace into scope. It belongs to PHP's low-level, event-driven XML Parser (SAX) extension and is unrelated to SimpleXML or DOM, which parse the whole document into a tree instead of streaming events.
You reach for this handler when you parse large or streaming XML and need to know which namespaces are active — for example, to map prefixes to URIs, to validate that a required namespace is present, or to dispatch elements to different processors based on their namespace.
Key requirement: namespace handlers only fire if the parser is namespace-aware. You must create the parser with
xml_parser_create_ns(), notxml_parser_create(). A plain parser silently ignoresxmlnsattributes, so this handler will never be called.
Syntax
xml_set_start_namespace_decl_handler($parser, $handler): bool| Parameter | Description |
|---|---|
$parser | A namespace-aware XML parser created by xml_parser_create_ns(). |
$handler | The callback to run on each start-namespace event. Pass a function name (string), a closure, or null to remove a previously set handler. |
The function returns true on success or false on failure.
The callback signature
Your handler receives three arguments:
function handler($parser, $prefix, $uri): void$parser— the parser that fired the event.$prefix— the namespace prefix, e.g."ns"forxmlns:ns="…". For a default namespace (xmlns="…") the prefix is the booleanfalse, not an empty string.$uri— the namespace URI the prefix is bound to.
Example: reading namespace declarations
The example below parses an Atom-style document with two namespaces and prints each one as it comes into scope. Note the use of xml_parser_create_ns() so the events actually fire:
function handleStartNamespace($parser, $prefix, $uri) {
// A default namespace (xmlns="...") arrives as prefix === false.
$name = ($prefix === false) ? "(default)" : $prefix;
echo "Namespace in scope -> $name = $uri\n";
}
$parser = xml_parser_create_ns();
xml_set_start_namespace_decl_handler($parser, "handleStartNamespace");
$xml = '<?xml version="1.0"?>
<root xmlns:ns="http://example.com/ns"
xmlns:meta="http://example.com/meta">
<ns:item>Test</ns:item>
</root>';
// The third argument `true` marks this as the final chunk of data.
xml_parse($parser, $xml, true);
xml_parser_free($parser);Output:
Namespace in scope -> ns = http://example.com/ns
Namespace in scope -> meta = http://example.com/metaThe parser raises one event per declared namespace, in the order the xmlns attributes appear, before it reports the element that declared them.
Common gotchas
- Plain parser, no events. If you create the parser with
xml_parser_create()instead ofxml_parser_create_ns(), the handler is never called and you'll see no output — a frequent source of "it doesn't work" confusion. - Default namespace prefix is
false. Always compare with===($prefix === false); anif (!$prefix)test also catches the legitimate prefix"0". - Pair with the end handler. The companion
xml_set_end_namespace_decl_handler()marks where a namespace goes back out of scope, which matters when you track nesting. - Free the parser. Call
xml_parser_free()when you're done to release the resource.
Related functions
xml_parser_create_ns()— create the namespace-aware parser this handler requires.xml_set_end_namespace_decl_handler()— the matching end-of-scope handler.xml_set_element_handler()— handle element start/end tags.xml_parse()— feed data to the parser and trigger the callbacks.
Conclusion
xml_set_start_namespace_decl_handler() lets you react to namespaces as they come into scope while streaming XML with the SAX parser. The single thing that trips people up is the parser: namespace events only fire when the parser is built with xml_parser_create_ns(). Remember that a default namespace arrives with a prefix of false, pair the handler with xml_set_end_namespace_decl_handler() when you need scope tracking, and free the parser when you're finished.