php SimpleXML检查孩子是否存在

时间:2009-10-13 15:04:04

标签: php simplexml

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

17 个答案:

答案 0 :(得分:117)

最好将其包装在isset()

if(isset($A->b->c)) { // c exists

如果$A$A->b不存在......那就不会爆炸。

答案 1 :(得分:39)

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

if( !empty($a->b)){
  var_dump($a->b);
}

答案 2 :(得分:8)

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

$identification = $xml->identification;
if (@count($identification->children()) == 0)
  $identification = $xml->Identification;

我讨厌这个......

答案 3 :(得分:7)

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

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

答案 4 :(得分:5)

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

if(false !== $A->xpath('b/c')) { ...

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

答案 5 :(得分:4)

如果你有PHP 5.3,你可以使用$a->count()。否则,使用@count($a->children())的scippie解决方案效果很好。我发现我不需要@,但较旧的PHP实现可能需要它。

答案 6 :(得分:2)

使用if(isset($A->b){ 给了我一些问题,所以我试过了 if($A->b){ 它有效!

答案 7 :(得分:2)

简单

var_dump(count($xml->node));

答案 8 :(得分:2)

使用xpath:

function has_child(\SimpleXMLElement $parent=null, string $xpathToChild)
{
    return isset($parent) && !empty($parent->xpath('('.$xpathToChild.')[1]'));
}

其中$parent是要检查的子节点的间接或直接父节点,$xpathToChild是相对于$parent的子节点的xpath。

()[1]是因为我们不想选择所有子节点。一个就够了。

检查$ a-> b-> c是否存在:

has_child($a,'b/c');

您还可以检查属性。检查节点c是否具有t属性。

has_child($a,'b/c/@t');

答案 9 :(得分:1)

我在PHP 5.5.23中确认工作的3种方法是使用isset() count()empty()

这是一个显示每个结果的脚本:

https://gist.github.com/mchelen/306f4f31f21c02cb0c24

答案 10 :(得分:1)

我使用辅助函数来检查节点是否是作为函数中的参数提供的有效节点。

private static function isValidNode($node) {
  return isset($node) && $node instanceof SimpleXMLElement && !empty($node);
}

用法示例:

public function getIdFromNode($node) {
  if (!self::isValidNode($node)) {
    return 0;
  }
  return (int)$node['id'];
}

答案 11 :(得分:1)

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

if (isset($A->b->c)) { /* c exists */ }

但是,其原因尚不清楚(至少对我而言),并且此页面上存在相当多的错误信息。我花了一些时间才能正确理解它,所以我想分享我学到的东西。

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

例如,如果b不存在:

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

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

但实际上并非如此:

isset($A->b); // returns false

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

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

此问题的另一个脚注-原始问题询问有关测试$A->b->c是否存在的问题。即使中间b不存在,也可以使用isset($A->b->c)完美地解决此问题。我认为这里发生的是PHP首先执行$A->b,如果b不存在,它将获取一个空的SimpleXMLElement,然后在该空的SimpleXMLElement上调用__isset('c')以获取{{ 1}}。

答案 12 :(得分:0)

你可以尝试:

if($A->b->c && $A->b->c != '')

答案 13 :(得分:0)

以为我会分享我的经验。运行在5.4我尝试使用'isset'和'empty'进行测试但是对我来说都没有用。我最终使用 is_null

if(!is_null($xml->scheduler->outterList->innerList)) {
    //do something
}

答案 14 :(得分:0)

名称空间

请注意,如果您在XML文件中使用名称空间,则在检查子项时需要在函数调用中包含名称空格,否则每次都会返回ZERO:

if ($XMLelement->children($nameSpace,TRUE)->count()){
    //do something here 
}

答案 15 :(得分:0)

我不能说早期版本,但在 PHP 8.0 中,使用以下单行函数:

function elementExists(?SimpleXMLElement $element) : bool {
  return is_null($element)?false:@count($element);
}

$A = new SimpleXMLElement('<A><b><c/></b></A>');  // doc contains c
$B = new SimpleXMLElement('<B><b/></B>');         // doc does not contain c 
$C = new SimpleXMLElement('<C><x><c/></x></C>');  // doc contains c but different heirarchy

print '$A contains ->b->c : ' . (elementExists($A->b->c)?"true":"false") . PHP_EOL;
print '$B contains ->b->c : ' . (elementExists($B->b->c)?"true":"false") . PHP_EOL;
print '$C contains ->b->c : ' . (elementExists($C->b->c)?"true":"false") . PHP_EOL;

返回

$A contains ->b->c : true
$B contains ->b->c : false
$C contains ->b->c : false

即。正确判断 c 是否存在以及是否在要求的位置。

答案 16 :(得分:-18)

if($A->b->c != null) //c exists

如果c不存在,则其值为null(或者更确切地说,它将没有值)。但请注意,为了实现这一点,Ab都不需要null。否则,PHP会抛出错误(我认为)。

相关问题