Vivek
Vivek

Reputation: 1493

How to get the next node in simplexml

I am using yahoo weather api and i want to get the forecast details but the XML is showing two nodes like this

<yweather:forecast day="Thu" date="23 May 2013" low="32" 
                   high="44" text="Clear" code="31"/>
<yweather:forecast day="Fri" date="24 May 2013" low="31" 
                   high="44" text="Sunny" code="32"/>

Now how i can select the 2nd one please help for getting the node i am using this code and i am getting the first node values only.

$myxml=new SimpleXMLElement("http://weather.yahooapis.com/forecastrss?w=$woeid[0]&u=c",NULL,TRUE);
$ab=$myxml->children();
$ad=$ab->channel->item->children('yweather',true)->forecast->attributes();

$fhigh=(string) $ad->high;
$flow=(string) $ad->low;
$ftemptype=(string) $ad->text;
$fdate=(string) $ad->date;

I am getting $flow as 32 and $fdate as 23 May 2013

Upvotes: 1

Views: 1237

Answers (3)

hakre
hakre

Reputation: 197787

If the next node means the next node with the same name as the current node and you access them via the parent node like in your case:

$ad = $ab->channel->item->children('yweather',true)->forecast->attributes();

Then the element-named ->forecast-> returns the first node of the same-named-element-children-simplexml-container. This can be also written as ->forecast[0]->. The second element therefore is ->forecast[1]->. Yes, that simple. Even this looks like an array, it's not one, but it works quite similar to one. So 0 is first element, 1 is second and so on:

$url = "http://weather.yahooapis.com/forecastrss?w=$woeid[0]&u=c";
$xml = simplexml_load_file($url);

$items     = $xml->channel->item;
$forecasts = $items[0]->children('yweather', true)->forecast;

print_r($forecasts[0]->attributes()); # Day 1
print_r($forecasts[1]->attributes()); # Day 2

As you can see in this example, I use the numeric indexes at quite some places. That makes the code even a little more saying.

The second tip I give is that you use better named variable names. They will help you a lot to not loose sight. And you can waste variables in PHP, PHP is very good with them, so use them a lot.

Hope this helps.

Upvotes: 0

Rolando Isidoro
Rolando Isidoro

Reputation: 5114

Here's a simple solution using SimpleXML and Xpath. Just replace the $myxml variable in my example with yours and it should be good to go:

<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">
    <channel>
        <title>Yahoo! Weather - Sunnyvale, CA</title>
        <link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_c.html</link>
        <description>Yahoo! Weather for Sunnyvale, CA</description>
        <language>en-us</language>
        <lastBuildDate>Thu, 23 May 2013 12:55 pm PDT</lastBuildDate>
        <ttl>60</ttl>
        <yweather:location city="Sunnyvale" region="CA" country="United States" />
        <yweather:units temperature="C" distance="km" pressure="mb" speed="km/h" />
        <yweather:wind chill="17" direction="360" speed="22.53" />
        <yweather:atmosphere humidity="48" visibility="16.09" pressure="1016.6" rising="0" />
        <yweather:astronomy sunrise="5:53 am" sunset="8:14 pm" />
        <image>
            <title>Yahoo! Weather</title>
            <width>142</width>
            <height>18</height>
            <link>http://weather.yahoo.com</link>
            <url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif</url>
        </image>
        <item>
            <title>Conditions for Sunnyvale, CA at 12:55 pm PDT</title>
            <geo:lat>37.37</geo:lat>
            <geo:long>-122.04</geo:long>
            <link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_c.html</link>
            <pubDate>Thu, 23 May 2013 12:55 pm PDT</pubDate>
            <yweather:condition text="Fair" code="34" temp="17" date="Thu, 23 May 2013 12:55 pm PDT" />
            <description><![CDATA[<img src="http://l.yimg.com/a/i/us/we/52/34.gif"/><br />
<b>Current Conditions:</b><br />
Fair, 17 C<BR />
<BR /><b>Forecast:</b><BR />
Thu - Sunny. High: 19 Low: 9<br />
Fri - Sunny. High: 21 Low: 11<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_c.html">Full Forecast at Yahoo! Weather</a><BR/><BR/>
(provided by <a href="http://www.weather.com" >The Weather Channel</a>)<br/>]]>    </description>
            <yweather:forecast day="Thu" date="23 May 2013" low="9" high="19" text="Sunny" code="32" />
            <yweather:forecast day="Fri" date="24 May 2013" low="11" high="21" text="Sunny" code="32" />
            <guid isPermaLink="false">USCA1116_2013_05_24_7_00_PDT</guid>
        </item>
    </channel>
</rss>
XML;

$myxml = new SimpleXMLElement($xml);
$myxml->registerXPathNamespace('yweather', 'http://xml.weather.yahoo.com/ns/rss/1.0');
$secondForecast = $myxml->xpath('//yweather:forecast[2]');
$ad             = $secondForecast[0]->attributes();

$fhigh     = (string) $ad->high;
$flow      = (string) $ad->low;
$ftemptype = (string) $ad->text;
$fdate     = (string) $ad->date;

echo "High: {$fhigh} Low: {$flow} Type: {$ftemptype} Date: {$fdate}\n";

Output:

High: 21 Low: 11 Type: Sunny Date: 24 May 2013

Upvotes: 1

Jerry
Jerry

Reputation: 3586

Probably the easiest thing to do is use a SimpleXMLIterator, which provides a simple interface to traverse your xml data. You would create the iterator, get the children, and then use next to move from one to the next.

Upvotes: 0

Related Questions