MyTetra Share
Делитесь знаниями!
php SimpleXML check if a child exists
Время создания: 22.07.2018 00:25
Текстовые метки: php simplexml exist node
Раздел: PHP

A->b->c might exist but c might not exist. How do I check it?


php simplexml

shareimprove this question

edited Jan 22 '15 at 11:39


peter-b

1,31042140

asked Oct 13 '09 at 15:04


An employee

1,96082541

Please select a new answer – Tim Ogilvy Apr 27 '17 at 9:58

add a comment

15 Answers

active oldest votes

up vote

-12

down vote

accepted

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

If c does not exist, its value will be null (or, to be more precise, it will have no value). Note, however, that for this to work, both A and b need to not be null. Otherwise, PHP will throw an error (I think).


shareimprove this answer

edited Nov 15 '16 at 15:20


TRiG

6,65243781

answered Oct 13 '09 at 15:17


Pim Jager

26k146492

18

This isn't a great idea. c will be an empty object if the node does not exist, which isn't the same as NULL. – spikyjt Jan 22 '13 at 11:15

4

To add to what @spikyjt said, if node c doesn't exist in $A->b, an empty SimpleXMLElement is returned. The valid instance of SimpleXMLElement is not null; that expression always evaluates true. – Matt Nov 19 '13 at 19:17

add a comment

up vote

106

down vote

It might be better to wrap this in an isset()


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

That way if $A or $A->b don't exist... it doesn't blow up.


shareimprove this answer

answered Oct 13 '09 at 18:41


null

4,99431826

13

This seemed neater than the other answers, but actually SimpleXMLElement returns and empty SimpleXMLElement object for any requested node that doesn't exist. So the empty() method seems like the best route. – spikyjt Jan 22 '13 at 11:22

also, c may be optional but A and b may be required, so I may actually want to get an exception if they are not defined - easy way to check document's integrity – davka Feb 28 '13 at 10:50

@spikyjt isset() is the best route to check if the node exists. You can use empty() if you need to check whether the node exists AND has something inside it, i.e. between > and < (either text or child nodes). If you need just to check for the existence of the node then empty() won't do. For example, empty() will return you true for this node <b a="zzz"></b> – CITBL Apr 18 '17 at 15:42

1

@CITBL you are correct, empty() is not much use. It is important to be aware however, that if there is no c element, isset($A->c) === false, but $A->c returns an empty SimpleXMLElement. So with $c = $A->c;, then isset($c) === true (i.e. $c !== null even though that might be expected). – spikyjt Apr 18 '17 at 22:14

add a comment

up vote

38

down vote

SimpleXML always return Object. If there is no child, empty object is returned.


if( !empty($a->b)){

var_dump($a->b);

}

shareimprove this answer

answered Mar 17 '11 at 20:03


CedCannes

39732

Apparently this is a feature and not a bug. And it is very important to note this. Accessing a child of the object will create it if it does not exist. – cosmin Apr 25 '13 at 14:50

2

This should be the accepted answer, would have saved me some time and frustration :-) – Niek Klein Kromhof May 24 '16 at 14:09

1

Wrong answer. Because empty() returns true even if the node exists but has no content. For example, in your code sample, if $a contains this: <xml><b a="zzz"/></xml> then empty($a->b) will return true. Therefore that's not a reliable way to check if a node exists. You can use empty() though if you need something inside a node, i.e. between > and <, and not interested in the node without content – CITBL Apr 28 '17 at 20:04

add a comment

up vote

7

down vote

I solved it by using the children() function and doing a count() on it, ignoring an PHP error if there are no children by putting an @ before the count-call. This is stupid, but it works:


$identification = $xml->identification;

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

$identification = $xml->Identification;

I hate this...


shareimprove this answer

edited Sep 13 '11 at 18:09


Jérôme Verstrynge

26.5k60211370

answered Nov 24 '10 at 15:11


scippie

98411331

8

+1 for "I hate this" :) – Ilari Kajaste Dec 19 '13 at 11:03

add a comment

up vote

6

down vote

Method xpath returns array of matched elements or false


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

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


shareimprove this answer

answered Sep 25 '13 at 10:32


user1391077

6911

1

No, the docs indicate it returns FALSE if there's an error, not if the path returned no results. – Brian Mar 14 '17 at 15:24

add a comment

up vote

4

down vote

After some experimentation, I've discovered that the only reliable method of checking if a node exists is using count($xml->someNode).


Here's a test case: https://gist.github.com/Thinkscape/6262156


shareimprove this answer

answered Apr 10 '14 at 12:52


Artur Bodera

1,4491518

add a comment

up vote

2

down vote

If you have PHP 5.3, you can just use $a->count(). Otherwise, scippie's solution using @count($a->children()) works well. I find I don't need the @ but older PHP implementations may need it.


shareimprove this answer

edited Sep 13 '11 at 18:09


Jérôme Verstrynge

26.5k60211370

answered Mar 23 '11 at 23:05


Alex Matulich

8111

add a comment

up vote

2

down vote

Using if(isset($A->b){ gave me issues, so I tried if($A->b){ and it worked!


shareimprove this answer

answered Jun 6 '12 at 12:49


Daydah

297517

2

count and cast to boolean are the two ways that makes sense. Using if as you describe is the shortest way to cast to boolean. – Brilliand Jan 6 '15 at 18:56

add a comment

up vote

1

down vote

Simply


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

shareimprove this answer

answered Mar 15 '17 at 18:04


Oğuz Can Sertel

425717

add a comment

up vote

0

down vote

You could try:


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

shareimprove this answer

edited Sep 13 '11 at 18:09


Jérôme Verstrynge

26.5k60211370

answered Jun 21 '11 at 16:08


jgrund

18112

add a comment

up vote

0

down vote

Thought I'd share my experience. Running on 5.4 I tried testing with 'isset' and 'empty' but neither worked for me. I ended up using is_null.


if(!is_null($xml->scheduler->outterList->innerList)) {

//do something

}

shareimprove this answer

answered Aug 2 '13 at 21:29


user857276

6771918

add a comment

up vote

0

down vote

Name Spaces


Be aware that if you are using name spaces in your XML file you will need to include those in your function calls when checking for children otherwise it will return ZERO every time:


if ($XMLelement->children($nameSpace,TRUE)->count()){

//do something here

}

shareimprove this answer

answered Oct 1 '14 at 17:26


g-man

544

add a comment

up vote

0

down vote

The 3 ways I can confirm work in PHP 5.5.23 were using isset() count() or empty()


Here is a script to show the results from each:


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


shareimprove this answer

answered Apr 15 '15 at 18:43


Mike Chelen

31928

add a comment

up vote

0

down vote

Using xpath:


function has_child(\SimpleXMLElement $parent=null, string $xpathToChild)

{

return isset($parent) && !empty($parent->xpath('('.$xpathToChild.')[1]'));

}

where $parent is an indirect or direct parent of the child node to check and $xpathToChild is an xpath to the child relative to $parent.


()[1] is because we don't want to select all the child nodes. One is enough.


To check if $a->b->c exists:


has_child($a,'b/c'); or has_child($a->b,'c');


You can also check for attributes. To check if the node c has the t attribute.


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

shareimprove this answer

edited Apr 18 '17 at 16:41

answered Apr 18 '17 at 13:09


CITBL

63221128

add a comment

up vote

0

down vote

I use a helper function to check if a node is a valid node provided as a parameter in function.


private static function isValidNode($node) {

return isset($node) && $node instanceof SimpleXMLElement && !empty($node);

}

Usage example:


public function getIdFromNode($node) {

if (!self::isValidNode($node)) {

return 0;

}

return (int)$node['id'];

}

 
MyTetra Share v.0.53
Яндекс индекс цитирования