php SimpleXML检查孩子是否存在

An *_*yee 59 php simplexml

A->b->c可能存在但c可能不存在.我该如何检查?

nul*_*ull 121

将它包装成一个可能更好 isset()

if(isset($A->b->c)) { // c exists
Run Code Online (Sandbox Code Playgroud)

这种方式,如果$A$A->b不存在......它不会爆炸.

  • 这似乎比其他答案更整洁,但实际上SimpleXMLElement为任何不存在的请求节点返回并清空SimpleXMLElement对象.所以empty()方法似乎是最好的路线. (14认同)
  • @CITBL你是对的,`empty()`没什么用.重要的是要注意,如果没有`c`元素,`isset($ A-> c)=== false`,但`$ A-> c`返回一个空的SimpleXMLElement.因此,使用`$ c = $ A-> c;`,然后`isset($ c)=== true`(即``$ c!== null`,即使这可能是预期的). (2认同)

小智 39

SimpleXML总是返回Object.如果没有子节点,则返回空对象.

if( !empty($a->b)){
  var_dump($a->b);
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案,会节省我一些时间和挫折:-) (3认同)
  • 错误的答案。因为`empty()`会返回`true`,即使该节点存在但不包含任何内容。例如,在您的代码示例中,如果$ a包含以下内容:<xml> <ba =“ zzz” /> </ xml>`,则`empty($ a-> b)`将返回true。因此,这不是检查节点是否存在的可靠方法。如果需要在节点内部(例如,在>>和<<之间)并且对没有内容的节点不感兴趣,可以使用`empty()`。 (2认同)

Dan*_*ard 9

@null 的答案是正确的 - 最简单的方法是isset

if (isset($A->b->c)) { /* c exists */ }
Run Code Online (Sandbox Code Playgroud)

然而,其原因并不明显(至少对我来说),并且此页面上有相当多的错误信息。我花了一段时间才正确理解它,所以我想分享我学到的东西。

正如一些人指出的那样,当您访问 SimpleXMLElement 不存在的子元素时,您得到的实际上是一个“空”SimpleXMLElement,而不是 false 或 null。

例如,如果 b 不存在:

$b = $A->b; // $b is now an empty SimpleXMLElement
$b->getName(); // returns an empty string
isset($b); // returns true
Run Code Online (Sandbox Code Playgroud)

所以你可能会认为使用isset来测试孩子是否存在是行不通的,因为如果孩子不存在,我们仍然得到一个空的SimpleXMLObject,所以isset必然返回true。

但事实上并非如此:

isset($A->b); // returns false
Run Code Online (Sandbox Code Playgroud)

这让我非常惊讶!原因是这isset不是一个常规函数,而是一个 PHP 语言构造。当您调用PHP 时isset($A->b),PHP 不会首先计算$A->b,然后将结果作为参数传递给isset(). 相反,在无法访问的对象属性上调用 isset 时的行为是调用__isset()类上的重载方法(如下所述: https: //www.php.net/manual/en/language.oop5.overloading.php#object)。伊塞特

因此,该类的作者可以isset($A->b)独立于 的结果来控制 的结果$b = $A->b。对于 SimpleXMLElement,他们将其设置为isset($A->b)如果 b 存在则返回 true,否则返回 false - 这正是我们测试子元素是否存在所需的。

对此的进一步脚注 - 最初的问题询问是否存在$A->b->cisset($A->b->c)即使中间 b 不存在,使用也可以完美地实现这一点。我认为这里发生的事情是 PHP 首先执行$A->b,如果 b 不存在,它会获取一个空的 SimpleXMLElement,然后调用__isset('c')该空的 SimpleXMLElement 来获取 的最终结果isset($A->b->c)


sci*_*pie 8

我通过使用children()函数并对其进行了解决,通过count()在count-call之前放置@来忽略PHP错误(如果没有子节点).这是愚蠢的,但它有效:

$identification = $xml->identification;
if (@count($identification->children()) == 0)
  $identification = $xml->Identification;
Run Code Online (Sandbox Code Playgroud)

我讨厌这个...


Art*_*era 8

经过一些实验,我发现检查节点是否存在的唯一可靠方法是使用count($xml->someNode).

这是一个测试用例:https://gist.github.com/Thinkscape/6262156


小智 5

方法xpath返回匹配元素的数组或false

if(false !== $A->xpath('b/c')) { ...
Run Code Online (Sandbox Code Playgroud)

http://www.php.net/manual/ru/simplexmlelement.xpath.php

  • 不,文档表明如果出现错误则返回FALSE,而不是路径返回没有结果. (2认同)

Pim*_*ger -26

if($A->b->c != null) //c exists
Run Code Online (Sandbox Code Playgroud)

如果c不存在,则其值将为null(或者更准确地说,它将没有值)。但请注意,要使其发挥作用, 和 都A不必bnull。否则,PHP 将抛出错误(我认为)。

  • 这不是一个好主意。如果节点不存在,c 将是一个空对象,这与 NULL 不同。 (22认同)
  • 添加到 @spikyjt 所说的内容,如果 $A->b 中不存在节点 c,则返回一个空的 SimpleXMLElement。SimpleXMLElement 的有效实例不为 null;该表达式的计算结果始终为 true。 (5认同)