December 5, 2008 at 5:25PM PHP SimpleXML bug: prefix required for attributes in namespace other than the default namespace
I’ve just submitted PHP Bug #46769. This bit me at work because it caused the tests for the EPP client code to start failing suddenly on my machine.
The story is that the fix for Bug #43221 made prefixes on attribute qnames required if the namespace of that attribute was anything other than the default namespace.
Previously to this ‘fix’, libxml2 was let do its job and was able to figure out what the prefix was from the namespace. The ‘fix’ prevents libxml2’s ability to do this.
Here’s the example I posted up demonstrating the bug:
<?php
$ns_foo = "tag:example.com,2008:foo";
$ns_xsi = "http://www.w3.org/2001/XMLSchema-instance";
$root_doc = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:xsi="$ns_xsi"
xmlns="tag:example.com,2008"
xsi:schemaLocation="tag:example.com,2008 root.xsd"
xmlns:foo="$ns_foo"/>
EOT;
$root = simplexml_load_string($root_doc);
$child = $root->addChild('bar', null, $ns_foo);
$child->addAttribute('schemaLocation', "$ns_foo foo.xsd", $ns_xsi);
print_r($root->asXml());
What should be happening and what was happening previously was that because the XML schema instance namespace was declared on a parent element of <foo:bar/>, the correct document was being generated:
<?xml version="1.0" encoding="UTF-8"?> <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="tag:example.com,2008" xmlns:foo="tag:example.com,2008:foo" xsi:schemaLocation="tag:example.com,2008 root.xsd"> <foo:bar xsi:schemaLocation="tag:example.com,2008:foo foo.xsd"/> </a>
However now this code triggers the warning “Warning: SimpleXMLElement::addAttribute(): Attribute requires prefix for namespace” and the attribute is no longer being added to <foo:bar/>.
This broke the EPP client badly because the code for building requests declares the namespaces on the root element of the document and relies on being able to reference them later by name. The upshot of this is that our EPP client (and, no doubt, other code) cannot be deployed on PHP 5.2.6 and later.
We’ll see how this is followed up. Suffice it to say that this is not the best start to the weekend, and that once again unit testing has displayed its awesomeness.