Jump to content

Trying to get property of non-object, simplexml question.


Recommended Posts

So I'm getting a "Notice: Trying to get property of non-object in" error when I'm trying to pull data from a xml.  I have a complete xml that has all of the potential node that it could ever have and it loads up fine -no errors, but when I load a different xml that doesn't have all of the possible nodes it returns this error several times here is a sample of my code:

$source = 'TestFile.xml';

$xml = new SimpleXMLElement($source,null,true);

$result = mysql_query("SELECT * FROM tblvalues") or die(mysql_error());

//Return the table row by row
while($row = mysql_fetch_array($result))
  {
    $curblk = substr($row['fldelement'],0,3);

    switch ($row['fldelement']){
        case "E06_04":
        case "E06_05":
        case "E06_07":
        case "E06_08":
            $cursub = $curblk."_04_0";
            $xmlVal = $xml->Header->Record->$curblk->$cursub->$row['fldelement']; //grab value from xml
            break;
        ...
        ...
        ... // the cases go on for a while...
        ...
        case "E07_05":
        case "E07_06":
        case "E07_07":
        case "E07_08":
            $cursub = $curblk."_03_0";
            $cursub2 = $curblk."_05_0";
            $xmlVal = $xml->Header->Record->$curblk->$cursub->$cursub2->$row['fldelement']; //this is the line that the error points to
            break;
        ...
        ...
        ...

 

And here is the sample of the xml that returns the error:

<E07>
    <E07_01>-20</E07_01> 
    <E07_02>0</E07_02> 
    <E07_15>-25</E07_15> 
    <E07_16>-25</E07_16> 
    <E07_17>-25</E07_17> 
    <E07_18_0>
      <E07_18_01>
        <E07_18>-20</E07_18> 
        <E07_19>-20</E07_19> 
        <E07_20>-20</E07_20> 
      </E07_18_01>
      ....
      ....
      ....

The obvious problem (to me) is that my code is trying to return a value from a nonexistent xml node, for example:

 

$xmlVal = $xml->Header->Record->$curblk->$cursub->$cursub2->$row['fldelement'];

 

is looking for:

 

$xmlVal = $xml->Header->Record->E07->E07_03_0->E07_05_0->E07_05

 

Ok, I get that, so how do I rewrite this so it's not blowing up on something so simple?

 

Quick notes:

-This same code works for a more complete xml

-Rewriting the xmls is not an option as I have no control over those

 

Edit: Almost forgot, thanks!

Even though I'm a noob, I'm still a little embarrassed to ask this...  Where/how would i apply the property_exists() function?  I've read up on it and from what I understand it returns either true or false but not the value...  Would i have to create a function to apply this check?  If so could I get and example?  I've looked around but I haven't found anything that really applies or at least I simply don't understand.

 

Basically what I want is, if the node is there - return its value, if not - I don't care as long as it isn't an error that will break my page.

nm, I got it figured out, kinda... I didn't use the property_exists(), rather I used the isset...  I still a noob so I have a hard time understanding the uses of of some of the functions.  Anyways, here is what I did:

 

$xmlVal = isset($xml->Header->Record->$curblk->$cursub->$cursub2->$row['fldelement']) ? $xml->Header->Record->$curblk->$cursub->$cursub2->$row['fldelement'] : $defualtVal;

If it's there, it grabs it, if not you get $defualtVal - most importantly not error!  Thank for the previous suggestion ignace, even though I didn't use it, it lead me down the right path!

In the case of SimpleXML you would have been able to omit the error's (and future error's) if you used a Proxy or wrapper, like:

 

class SimpleXMLElementWrapper implements ArrayAccess {
    private $simpleXML;
    
    function __construct(SimpleXMLElement $simplexml = null) {
        $this->simpleXML = $simpleXML;
    }
    
    function __get($offset) {
        if($this->simpleXML && property_exists($offset, $this->simpleXML)) {
            $value = $this->simpleXML->$offset;
            if($value instanceof SimpleXMLElement) {
                return new self($value);
            } else {
                return $value;
            }
        }
        return new self();
    }
    
    function __call($method, $args) {
        if($this->simpleXML && method_exists($method, $this->simpleXML)) {
            return call_user_method_array(array($this->simpleXML, $method), $args);
        }
        return array();
    }
    
    function __toString() {
        return ''.$this->simpleXML;
    }
}

 

This is a mere example that is not guaranteed to work but shows you how you can omit the nasty exceptions SimpleXML throws for your current and future projects. A usage example would be:

 

$simplexml = new SimpleXMLElementWrapper(new SimpleXMLElement('file.xml'));
$simplexml->foo->bar->baz;

 

Although foo bar and baz don't exist it won't throw any exceptions. It should be noted that it's not advised to use this code everytime you use SimpleXMLElement just to omit the problems you can encounter because it makes your code impossible to debug although you could resolve this by passing an extra paramter to SimpleXMLElementWrapper ($throwException) that changes wether or not it shall throw an exception when it can't find an offset.

 

I'm telling you this because for a current project I had to run through an XML that may or may not contain some tags and instead of writing a bunch of isset() statements I wrote a wrapper that returned an empty string instead.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.