PHP SimpleXML is broken: Part 1

The following code does not work as expected:

$xml = simplexml_load_string("<root><a/><b>text</b></root>");
$node = $xml->xpath("/root/a")[0];
if ($node) process($node); // process($node) may not be called for some valid nodes

Unlike most other objects, SimpleXmlElement may evaluate as false even when it is not null. Specifically, SimpleXmlElements representing empty tags (like “<a />) will evaluate as false, so process($node) won’t be called for them.

Yes, they made a special case for it in the language definition. E.g. DOMElement representing an empty tag won’t evaluate to false, at least not according to the documentation.

So, in my previous post “Node is null” should read “Node evaluates to false”, but it is still a bug, since it was not an empty tag.

When you write if (something) that something will be converted to Boolean per the below conversion rules. Most of them make sense, but some of them totally don’t. If you want to check for null, you’d better do it explicitly: if (something !== null).

PHP Boolean Conversion Rules

Per the PHP documentation on Boolean (comments are mine):

When converting to boolean, the following values are considered FALSE:

the boolean FALSE itself Totally makes sense
the integer 0 (zero) Like in C/C++, so it is expected, even if may not make perfect sense
the float 0.0 (zero) Like in C/C++, so it is expected, even though it makes even less sense
the empty string Not like in C/C++, but sort of makes sense
and the string “0” Why?! Because it represents integer 0? How about string “0.0” then? Or string “false”?
an array with zero elements Sort of makes sense
an object with zero member variables (PHP 4 only) Does not make sense, but they deprecated it
the special type NULL (including unset variables) Totally makes sense
SimpleXML objects created from empty tags Why?! Who came up with this wonderful idea?

Rest in peace, dear rule of least astonishment. You should never have ventured in that cruel PHP land.

Leave a Reply

Your email address will not be published. Required fields are marked *