Check for property's existence without getting "Node no longer exists" warning
Asked Answered
K

4

11

I'm using SimpleXML. If the user input to my function is invalid, my variable $x is an empty SimpleXMLElement Object; otherwise, it has a populated property $x->Station. I want to check to see if Station exists.

private function parse_weather_xml() {
    $x = $this->weather_xml; 
    if(!isset($x->Station)) {
        return FALSE;
    }

    ...
}

This does what I want, except it returns an error:

Warning: WeatherData::parse_weather_xml(): Node no longer exists in WeatherData->parse_weather_xml() (line 183 of vvdtn.inc).

Okay, so isset() is out. Let's try this:

private function parse_weather_xml() {
    $x = $this->weather_xml; 
    if(!property_exists($x, 'Station')) {
        return FALSE;
    }

    ...
}

This behaves almost identically:

Warning: property_exists(): Node no longer exists in WeatherData->parse_weather_xml() (line 183 of vvdtn.inc)

All right, fine, I'll turn it into an exception and disregard it. I've never done this before and I'm not sure I'm doing it right, but I'll give it a try:

function crazy_error($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

...

    private function parse_weather_xml() {
        set_error_handler('crazy_error');
        $x = $this->weather_xml; 
        if(!property_exists($x, 'Station')) {
            return FALSE;
        }
        restore_error_handler();

        ...
    }

That returns its own HTML page:

Additional uncaught exception thrown while handling exception.

Original

ErrorException: property_exists(): Node no longer exists in crazy_error() (line 183 of vvdtn.inc).

Additional

ErrorException: stat(): stat failed for /sites/default/files/less/512d40532e2976.99442935 in crazy_error() (line 689 of /includes/stream_wrappers.inc).


So now I'm laughing hysterically and giving up. How can I check for the existence of a property of a SimpleXML object without getting this error in one form or another?

Kilimanjaro answered 26/2, 2013 at 23:27 Comment(6)
I probably won't check this post until it's about 15 hours old; I don't want to look at this stupid problem anymore today.Kilimanjaro
You say you want to disregard the error, yet you are throwing it and not catching it... I might be wrong but...Marder
I couldn't be sure without the context of the code, but I suspect SimpleXML is complaining that $x (AKA $this->weather_xml) itself is not set, not that it doesn't contain a Station node.Gonagle
@Gonagle It is set; it's an empty SimpleXML object. See my second sentence above. A good thought, but already accounted for.Kilimanjaro
please consider to accept an answer (click tick mark on the left) if it actually answered your questionGeld
I'm getting the same issue here, did you find a solution at the end? @75thTromboneHoskinson
G
1

Do you want to check if your simplexml contains a certain node or not? --> count them!

EDIT: errors when node doesn't exist --> try xpath:

if ($xml->xpath("//station")->Count()==0) echo "no station!";

will throw error if no station-node:

Say $xml is your simplexml and stationis on the top-level:

 if ($xml->station->Count()==0) echo "no station!";

If 'station' is, say, a child of <something>, you'd of course go...

... $xml->something->station->Count();
Geld answered 26/2, 2013 at 23:33 Comment(4)
Note that $xml-station->Count() (or ->count()?) can be more idiomatically written as count($xml-station). SimpleXML is nice like that.Gonagle
Unfortunately, this returns the same error. Warning: count(): Node no longer exists in WeatherData->parse_weather_xml() (line 183 of vvdtn.inc). I've managed to get more errors like this from unrelated functions nearby, so I gave up and moved my logic to an earlier function, where the XML is originally fetched. All seems to work now, so this question is now purely academic.Kilimanjaro
@Geld For ->xpath() you can't use ->Count() - it returns an ordinary PHP array. (I think the principle is that it's like a set of search results from throughout the document, whereas SimpleXML objects always represent some contiguous section of the XML document)Gonagle
@Gonagle ok, I'm struggling with this topic, mind looking at this? #15167574Geld
D
0
if (!$x || !$x->Station) {
    return false;
}

Important thing - !$x - you need check this xml object for empty. If it is true then on any try resolve $x->Station you can get this error.

Deiform answered 1/3, 2017 at 5:18 Comment(0)
H
0

First check if by mistake you tried to access a property without checking before the bit of code you are trying to check (sometimes the error message is not accurate with the line numbers).

Then I used isset and it works fine:

 if(isset($xml->element))
 {
      // $xml has element 
 }
Hoskinson answered 30/8, 2017 at 21:56 Comment(0)
U
0

Have you tried property_exists()?

private function parse_weather_xml() {
  $x = $this->weather_xml; 
  if(!property_exists($x,"Station")) {
    return FALSE;
  }
...
}

And take into consideration this note:

As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
Ulphi answered 2/9, 2017 at 8:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.