Bug #68507 [Com]: SimpleXML objects casted to boolean inconsistently
| From: | jdomenechbborges at gmail dot com | Date: | Wed, 11 Jan 2017 11:19:01 +0000 |
| Subject: | Bug #68507 [Com]: SimpleXML objects casted to boolean inconsistently | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-206514@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68507&edit=1
ID: 68507
Comment by: jdomenechbborges at gmail dot com
Reported by: dmitri dot sologoubenko at gmail dot com
Summary: SimpleXML objects casted to boolean inconsistently
Status: Open
Type: Bug
Package: SimpleXML related
Operating System: Ubuntu
PHP Version: 5.5.19
Block user comment: N
Private report: N
New Comment:
The issue seems to be solved slowly in the next releases starting from PHP 5.4 and in PHP 7.0 seems
completely solved.
Test site
---------
http://phptester.net/
Result in 5.6
-------------
$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'; : 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 [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
Result in 7.0
-------------
$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'; : 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 [c]: <c>oink</c>
- 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 [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'; : true
- if((boolean)$CHILD) return 'true'; else return 'false'; : true
- (($CHILD)?'true':'false'): true
- ((true == $CHILD)?'true':'false'): true
- (((boolean)$CHILD)?'true':'false'): true
Previous Comments:
------------------------------------------------------------------------
[2014-12-09 11:10:25] seo at gacek dot vot dot pl
Also consider reading:
http://stackoverflow.com/questions/27156276/how-does-php-simplexml-get-evaluated-as-an-expression/27157104?noredirect=1#comment43066341_27157104
and https://bugs.php.net/bug.php?id=68540&thanks=4
for more refference about problem.
------------------------------------------------------------------------
[2014-11-26 18:37:26] dmitri dot sologoubenko at gmail dot com
Seems like the general rule - here - is, for bare objects as conditional expressions:
the SimpleXML object is considered "true" only and only if it:
a) has content or children, and also
b) has attributes
otherwise it is considered "false" (if block not executed).
Comparison to true follows different rules, and so does explicit casting to boolean. Only comparison
to boolean follows the description in documentation (and that's implicit casting to boolean!).
------------------------------------------------------------------------
[2014-11-26 18:28:34] dmitri dot sologoubenko at gmail dot com
Description:
------------
As per PHP documentation (online, see http://php.net/manual/en/control-structures.if.php):
> 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
Children elements "b" and "d" ARE empty (no content), 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 conditional
expression evaluates differently from a cast to boolean.
Test script:
---------------
<?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";
}
Expected result:
----------------
$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"; : 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 [c]: <c>oink</c>
- 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 [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"; : true
- if((boolean)$CHILD) return "true"; else return "false"; : true
- (($CHILD)?"true":"false"): true
- ((true == $CHILD)?"true":"false"): true
- (((boolean)$CHILD)?"true":"false"): true
Actual result:
--------------
$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
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68507&edit=1