考虑这个PHP代码:
<?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";
}
根据PHP文档(在线,请参阅http://php.net/manual/en/control-structures.if.php):
如关于表达式的部分所述,将评估表达式 到它的布尔值。如果expression的计算结果为TRUE,那么PHP将会 执行语句,如果计算结果为FALSE - 它将忽略它。 有关哪些值评估为FALSE的更多信息,请参阅 '转换为布尔值'部分。
此解释的“转换为布尔”部分说明:
转换为布尔值 转换为布尔值时,以下值被视为FALSE: ... ... omissis
从空标记
创建的SimpleXML对象
如果执行上面的代码,这些是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
儿童元素“b”和“d”是空的,因此我期待“假”,而“a”,“c”,“e”不是空的,所以我期待“真实”。
正如出来的那样,PHP文档中的该语句绝对不正确,并且行为甚至看起来不一致:对布尔值的隐式或显式强制转换的行为方式不同(参见元素“c”的情况)如果将简单的SimpleXML对象用作“if”条件表达式(“if”和“三元运算符”),那么表达式的某种方式与转换为布尔值的方式不同。
有没有人知道这里发生了什么?
答案 0 :(得分:0)
首先,让我们丢弃你的一些代码。
foreach ( $xml->children() as $child ) {
echo "\$CHILD [" . htmlspecialchars($child->getName()) . "]: " . htmlspecialchars($child->asXML());
echo "\n";
$insideIf1 = false;
if ($child) { $insideIf1 = true; }
$insideIf2 = false;
if (true == $child) { $insideIf2 = true; }
$insideIf3 = false;
if ((boolean)$child) { $insideIf3 = true; }
var_dump($child);
// echo intval($child)."\n";
echo 'VALUE EVALUATES TO: '. $child."\n";
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";
// This part evaluated exactly same as above. So no need to make confusion
echo "\n";
}
下一步:
第一次和第三次测试
那些基本相同。如果对象具有属性,则该对象被视为true。所以基本上没有属性的xml标签没有属性(只是var_dump它们)。
没有属性的对象(没有属性但是注意它们可以有值 - 由迭代器返回)被视为错误:c
,d
第二次测试
另一方面,该测试不测试对象本身。但是它从cast转换为:int,bool和string返回的所有值。
其中一项测试需要__toString
魔法。哪个返回值。然后它评估为true
(元素a
和c
)
所以它不是随机的,但在考虑它是真还是假时有特殊规则。
忘记添加
注意:SimpleXML已经规定了向大多数方法添加迭代属性的规则。无法使用var_dump()或其他任何可以检查对象的内容来查看它们。
这种“奇怪”的行为是它实施内行者的结果。
编辑:
正如您在评论中所述,是什么让您分析这种行为。我认为你永远不应该选择if($obj)
来检查SimpleXML对象
而是使用SimpleXML::attributes()
或strval
进行所有检查。然后你确定你在检查什么。
EDIT2:
$ xmlObject如果具有属性OR
Chilren (子节点),则认为是真的(不为空)(运行正常)
要检查对象是否具有值,请将其强制转换为字符串。
在这种情况下,空并不意味着它是否具有值,只有它具有子项或属性。