How does PHP SimpleXML get evaluated as an expression?



Consider this PHP code:



<?php
$xmlString =
'<'.'?xml version="1.0" encoding="UTF-8"?'.'>' .
'<rootEl>' .
'<a attrA="valA">xxx</a>' .
'<b attrB="valB"/>' .
'<c>oink</c>' .
'<d/>'.
'<e>' .
'<f>zzz</f>' .
'</e>' .
'</rootEl>';

$xml = simplexml_load_string( $xmlString );
foreach ( $xml->children() as $child ) {
echo "\$CHILD [" . $child->getName() . "]: " . $child->asXML();
echo "\n";
$insideIf1 = false;
if ($child) { $insideIf1 = true; }
$insideIf2 = false;
if (true == $child) { $insideIf2 = true; }
$insideIf3 = false;
if ((boolean)$child) { $insideIf3 = true; }

echo " - if(\$CHILD) return \"true\"; else return \"false\"; : " . (($insideIf1)?"true":"false")."\n";
echo " - if(true == \$CHILD) return \"true\"; else return \"false\"; : " . (($insideIf2)?"true":"false")."\n";
echo " - if((boolean)\$CHILD) return \"true\"; else return \"false\"; : " . (($insideIf3)?"true":"false")."\n";

echo " - ((\$CHILD)?\"true\":\"false\"): " . (($child)?"true":"false")."\n";
echo " - ((true == \$CHILD)?\"true\":\"false\"): " . ((true == $child)?"true":"false")."\n";
echo " - (((boolean)\$CHILD)?\"true\":\"false\"): " . (((boolean)$child)?"true":"false")."\n";

echo "\n";
}


As per PHP documentation (online, see http://ift.tt/1ChpHl9):



As described in the section about expressions, expression is evaluated to its Boolean value. If expression evaluates to TRUE, PHP will execute statement, and if it evaluates to FALSE - it'll ignore it. More information about what values evaluate to FALSE can be found in the 'Converting to boolean' section.



The "converting to boolean" section of this explanation states:



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


SimpleXML objects created from empty tags



If you execute the code above, these are the results on my PHP 5.5.9-1ubuntu4.5 (cli):



$CHILD [a]: <a attrA="valA">xxx</a>
- if($CHILD) return "true"; else return "false"; : true
- if(true == $CHILD) return "true"; else return "false"; : true
- if((boolean)$CHILD) return "true"; else return "false"; : true
- (($CHILD)?"true":"false"): true
- ((true == $CHILD)?"true":"false"): true
- (((boolean)$CHILD)?"true":"false"): true

$CHILD [b]: <b attrB="valB"/>
- if($CHILD) return "true"; else return "false"; : true
- if(true == $CHILD) return "true"; else return "false"; : false
- if((boolean)$CHILD) return "true"; else return "false"; : true
- (($CHILD)?"true":"false"): true
- ((true == $CHILD)?"true":"false"): false
- (((boolean)$CHILD)?"true":"false"): true

$CHILD [c]: <c>oink</c>
- if($CHILD) return "true"; else return "false"; : false
- if(true == $CHILD) return "true"; else return "false"; : true
- if((boolean)$CHILD) return "true"; else return "false"; : false
- (($CHILD)?"true":"false"): false
- ((true == $CHILD)?"true":"false"): true
- (((boolean)$CHILD)?"true":"false"): false

$CHILD [d]: <d/>
- if($CHILD) return "true"; else return "false"; : false
- if(true == $CHILD) return "true"; else return "false"; : false
- if((boolean)$CHILD) return "true"; else return "false"; : false
- (($CHILD)?"true":"false"): false
- ((true == $CHILD)?"true":"false"): false
- (((boolean)$CHILD)?"true":"false"): false

$CHILD [e]: <e><f>zzz</f></e>
- if($CHILD) return "true"; else return "false"; : true
- if(true == $CHILD) return "true"; else return "false"; : false
- if((boolean)$CHILD) return "true"; else return "false"; : true
- (($CHILD)?"true":"false"): true
- ((true == $CHILD)?"true":"false"): false
- (((boolean)$CHILD)?"true":"false"): true


Children elements "b" and "d" ARE empty, therefore I was expecting "false", and "a", "c", "e" ARE NOT empty, so I was expecting "true".


As is comes out, that statement in PHP documentation is absolutely NOT true, and the behaviour doesn't even seem consistent: implicit or explicit casts to boolean don't behave the same way (see case of element "c"), and if the bare SimpleXML object is used as "if" conditional expression (both "if" and ternary operator), somehow that expression evaluates differently from a cast to boolean.


Does anyone have an idea of what's going on here?


No comments:

Post a Comment