PHP DOM XML default namespaces

Anyone that’s used PHP’s DOM XML knows that it’s a deprecated, buggy PoS. An undocumented memory leak in DOM XML resources and an equally undocumented workaround to manually free them are plenty of evidence for this. Spare a thought for those of us who are on supported RHEL4 and stuck with PHP 4 and hence the DOM XML API.

My gripe today is with create_element_ns. Terence Kearns has a pretty good summary of the issue in his comments. Essentially, you cannot add a namespace to a node with the default prefix in a way that is recognised by the rest of DOM XML. The problem is that supplying an empty $prefix parameter to create_element_ns is treated the same as omitting the $prefix parameter altogether, in which case DOM XML generates a random prefix.

The libxml2 convention is that passing a NULL prefix to xmlNewNs binds the default namespace, while passing an empty string is illegal. Unfortunately, this convention might break a lot of PHP code that relies on DOM XML generating random namespace prefixes, because people are more likely to omit $prefix than to supply an empty string when they want the random-prefix behaviour. However, I figure it’s better to break lazy code than to invert the libxml convention.

My patch changes the DOM XML behaviour so that an empty string prefix such as $doc->create_element_ns('foo', 'http://example.net', '') activates the old DOM XML random-prefix:

   <a1337:foo xmlns:a1337="http://example.net" />

while omitting $prefix altogether as in $doc->create_element_ns('foo', 'http://example.net') binds the default namespace:

   <foo xmlns="http://example.net" />