1

Im trying to parse XML in PHP, but I am having problems with it.

So the XML looks like this (simplified)

<weatherdata>
 <forecast>
 <tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04" />
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46" />
   </time>

.....

I was able to load all the time->from values like this:

foreach($xml->forecast->tabular as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];       
}

But then I tried to load the name attribute of the symbol like this:

foreach($xml->forecast->tabular as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];
    $attr2 = $forecastItem->symbol->attributes();
    $names[] = $attr2['name'];
}

and it shows me an error that main() node does not exist. Basically what I would like to do is load all the names into an array, just like the froms.

0

2 Answers 2

2

The full error message you get is:

Warning: main(): Node no longer exists in ...

followed by the line-number of the following code:

$attr2 = $forecastItem->symbol->attributes();

It might not be clear to you what the error actually is about. To better understand it you have to know a little about the inner working of the SimpleXmlElement you make use of here.

If you access a child-element by it's name, for examle like here the <symbol> element:

$forecastItem->symbol

the SimpleXML extension will create the node on-the-fly as a temporary one, whenever no such child-element already exists. This is done to allow adding it on the fly. For example:

$forecastItem->symbol = 'hello world!';

echo $forecastItem->asXML();

would display:

<tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04"/>
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46"/>
   </time>
 <symbol>hello world!</symbol></tabular>
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

And that also explains why your code does not work. As the symbol element is only temporary, and you don't set it, SimpleXML just tries to tell you, that this node doesn't exist any longer. And rightly so, as you try to read the attributes from a non-existing node:

$forecastItem->symbol->attributes(); // no write, but a read operation

So it then works as expected if the node exists, e.g. this existing symbol element:

$forecastItem->time->symbol->attributes();

Which most likely is a sign you located yourself at a different location in the document tree when writing the code.

Sign up to request clarification or add additional context in comments.

Comments

1

You should use $xml->forecast->tabular->children() to traverse the children of the xml:

<?php

$data = '<weatherdata>
 <forecast>
 <tabular>
   <time from="2015-09-25T20:00:00" to="2015-09-25T23:00:00" period="3">
      <symbol number="4" numberEx="4" name="Cloudy" var="04" />
   </time>
   <time from="2015-09-25T23:00:00" to="2015-09-26T05:00:00" period="0">
      <symbol number="9" numberEx="46" name="Light rain" var="46" />
   </time>
  </tabular>
  </forecast>
  </weatherdata>';

$xml = simplexml_load_string($data);

$froms = array();
$names = array();

foreach($xml->forecast->tabular->children() as $forecastItem){
    $attr = $forecastItem->attributes();
    $froms[] = $attr['from'];
    $attr2 = $forecastItem->symbol->attributes();
    $names[] = $attr2['name'];
}

print_r($froms);
print_r($names);

Output:

Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => 2015-09-25T20:00:00
        )

    [1] => SimpleXMLElement Object
        (
            [0] => 2015-09-25T23:00:00
        )

)
Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => Cloudy
        )

    [1] => SimpleXMLElement Object
        (
            [0] => Light rain
        )

)

2 Comments

@Alan thanks, I just noticed that too, seems like we edited it at the same time.
No problem, what matters is that it's now corrected. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.