Solved

Parsing dynamic external XML file using PHP 4

Posted on 2009-04-08
3
8,945 Views
Last Modified: 2012-05-06
Hey Everybody,

PHP Version: 4.4.3

I'm having trouble Loading in a Dynamic, External XML File. I'm trying to work on a Weather widget for my website using a XML file that Yahoo! Weather provides.

The URL to the dynamic XML can be found here: http://weather.yahooapis.com/forecastrss?p=USOH0245

In the code view, I posted an example of the XML that is pulled back. I need to be able to load in the XML, and need to get to each attribute.

I built something on my local machine using SimpleXML, then realized my local machine is running PHP 5.

I need to basically need to be able to pull out each variable and use them however I please, but I can't seem to find any tutorials or even example in PHP4.

Any help is greatly appreciated.


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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 - Dayton, OH</title>
		<link>http://us.rd.yahoo.com/dailynews/rss/weather/Dayton__OH/*http://weather.yahoo.com/forecast/USOH0245_f.html</link>
		<description>Yahoo! Weather for Dayton, OH</description>
		<language>en-us</language>
		<lastBuildDate>Wed, 08 Apr 2009 12:56 pm EDT</lastBuildDate>
		<ttl>60</ttl>
		<yweather:location city="Dayton" region="OH" country="US"/>
		<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
		<yweather:wind chill="43" direction="270" speed="17"/>
		<yweather:atmosphere humidity="36" visibility="10" pressure="29.74" rising="2"/>
		<yweather:astronomy sunrise="7:09 am" sunset="8:08 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/us/nws/th/main_142b.gif</url>
		</image>
		<item>
			<title>Conditions for Dayton, OH at 12:56 pm EDT</title>
			<geo:lat>39.77</geo:lat>
			<geo:long>-84.2</geo:long>
			<link>http://us.rd.yahoo.com/dailynews/rss/weather/Dayton__OH/*http://weather.yahoo.com/forecast/USOH0245_f.html</link>
			<pubDate>Wed, 08 Apr 2009 12:56 pm EDT</pubDate>
			<yweather:condition text="Partly Cloudy" code="30" temp="49" date="Wed, 08 Apr 2009 12:56 pm EDT"/>
			<description>
				<![CDATA[<img src="http://l.yimg.com/a/i/us/we/52/30.gif"/><br />
					<b>Current Conditions:</b><br />
					Partly Cloudy, 49 F<BR />
					<BR /><b>Forecast:</b><BR />
					Wed - Partly Cloudy. High: 54 Low: 34<br />
					Thu - Mostly Sunny. High: 61 Low: 45<br />
					<br />
					<a href="http://us.rd.yahoo.com/dailynews/rss/weather/Dayton__OH/*http://weather.yahoo.com/forecast/USOH0245_f.html">Full Forecast at Yahoo! Weather</a><BR/>
					(provided by The Weather Channel)<br/>]]>
			</description>
			<yweather:forecast day="Wed" date="8 Apr 2009" low="34" high="54" text="Partly Cloudy" code="30"/>
			<yweather:forecast day="Thu" date="9 Apr 2009" low="45" high="61" text="Mostly Sunny" code="34"/>
			<guid isPermaLink="false">USOH0245_2009_04_08_12_56_EDT</guid>
		</item>
	</channel>
</rss>
<!-- api1.weather.ac4.yahoo.com uncompressed Wed Apr  8 10:54:56 PDT 2009 -->

Open in new window

0
Comment
Question by:BGHTechGuru
  • 2
3 Comments
 
LVL 7

Assisted Solution

by:Thomas Wheeler
Thomas Wheeler earned 20 total points
ID: 24100293
you should use something like this rss_reader class
<?php
 
class RSS_reader {
 
        public $title = false;
        public $date = false;
        public $link = false;
        public $description = false;
        public $titletext = null;
        public $linktext = null;
        public $desctext = null;
        public $strdate = null;
   public $xmlParser = null;
        public $fp = null;
        public $feed = null;
        public $cnt = 0;
        public $tmp = null;
 
  // function: startElement
 
  // Deals with the starting element
 
  function startElement( $parser, $tagName, $attrs ) {
 
    // By setting global variable of tag name
 
    // I can determine which tag I am currently
 
    // parsing.
 
    switch( $tagName ) {
 
      case 'TITLE':
 
        $this->title = true;
 
        break;
 
      case 'LINK':
 
        $this->link = true;
 
        break;
 
      case 'DESCRIPTION':
 
        $this->description = true;
 
        break;
 
       case 'DC:DATE':
        $this->date = true;
       break;
 
    }
 
  }
 
 
  function endElement( $parser, $tagName ) {
 
    switch( $tagName ) {
 
                case 'DC:DATE':
 
                                $this->tmp[0] = $this->strdate;
                        $this->date = false;
                        $this->strdate = "";
 
                break;
 
      case 'TITLE':
 
                        $this->tmp[1] = $this->titletext;
 
        $this->title = false;
        $this->titletext = "";
 
        break;
 
      case 'LINK':
 
                        $this->tmp[2] = $this->linktext;
 
        $this->link = false;
        $this->linktext = "";
 
        break;
 
      case 'DESCRIPTION':
 
                        $this->tmp[3] = $this->desctext;
 
        $this->description = false;
        $this->desctext = "";
 
        //Create feed Array//
                $this->feed[$this->cnt] = $this->tmp;
 
                $this->tmp = null;
                  //Increment counter//
                        $this->cnt++;
        break;
 
    }
 
 
 
  }
 
 
  function charElement( $parser, $text ) {
 
            if( $this->title == true ) {
 
                $this->titletext .= htmlspecialchars( trim($text) );
 
            } else if( $this->link == true ) {
 
                $this->linktext  .= trim( $text );
 
            } else if( $this->description == true ) {
 
                $this->desctext .= htmlspecialchars( trim( $text ) );
 
            } else if( $this->date == true ){
                $this->strdate .= trim( $text );
            }
 
  }

Open in new window

0
 

Author Comment

by:BGHTechGuru
ID: 24100916
From what I'm seeing, this would get the main nodes, but how would I pull out the attributes?

Maybe I'm looking at this wrong though, can you show me an example?
0
 

Accepted Solution

by:
BGHTechGuru earned 0 total points
ID: 24101644
Actually, I found a solution a little bit ago.

I used this script from Whoooop: http://whoooop.co.uk/2005/03/20/xml-to-array/

Here is the code that worked:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Weather Widget</title>
</head>
 
<body>
 
<?php
function GetXMLTree ($xmldata)
{
	// we want to know if an error occurs
	ini_set ('track_errors', '1');
 
	$xmlreaderror = false;
 
	$parser = xml_parser_create ('ISO-8859-1');
	xml_parser_set_option ($parser, XML_OPTION_SKIP_WHITE, 1);
	xml_parser_set_option ($parser, XML_OPTION_CASE_FOLDING, 0);
	if (!xml_parse_into_struct ($parser, $xmldata, $vals, $index)) {
		$xmlreaderror = true;
		echo "error";
	}
	xml_parser_free ($parser);
 
	if (!$xmlreaderror) {
		$result = array ();
		$i = 0;
		if (isset ($vals [$i]['attributes']))
			foreach (array_keys ($vals [$i]['attributes']) as $attkey)
			$attributes [$attkey] = $vals [$i]['attributes'][$attkey];
 
		$result [$vals [$i]['tag']] = array_merge ($attributes, GetChildren ($vals, $i, 'open'));
	}
 
	ini_set ('track_errors', '0');
	return $result;
}
 
function GetChildren ($vals, &$i, $type)
{
	if ($type == 'complete') {
		if (isset ($vals [$i]['value']))
			return ($vals [$i]['value']);
		else
			return '';
	}
 
	$children = array (); // Contains node data
 
	/* Loop through children */
	while ($vals [++$i]['type'] != 'close') {
		$type = $vals [$i]['type'];
		// first check if we already have one and need to create an array
		if (isset ($children [$vals [$i]['tag']])) {
			if (is_array ($children [$vals [$i]['tag']])) {
				$temp = array_keys ($children [$vals [$i]['tag']]);
				// there is one of these things already and it is itself an array
				if (is_string ($temp [0])) {
					$a = $children [$vals [$i]['tag']];
					unset ($children [$vals [$i]['tag']]);
					$children [$vals [$i]['tag']][0] = $a;
				}
			} else {
				$a = $children [$vals [$i]['tag']];
				unset ($children [$vals [$i]['tag']]);
				$children [$vals [$i]['tag']][0] = $a;
			}
 
			$children [$vals [$i]['tag']][] = GetChildren ($vals, $i, $type);
		} else
			$children [$vals [$i]['tag']] = GetChildren ($vals, $i, $type);
		// I don't think I need attributes but this is how I would do them:
		if (isset ($vals [$i]['attributes'])) {
			$attributes = array ();
			foreach (array_keys ($vals [$i]['attributes']) as $attkey)
			$attributes [$attkey] = $vals [$i]['attributes'][$attkey];
			// now check: do we already have an array or a value?
			if (isset ($children [$vals [$i]['tag']])) {
				// case where there is an attribute but no value, a complete with an attribute in other words
				if ($children [$vals [$i]['tag']] == '') {
					unset ($children [$vals [$i]['tag']]);
					$children [$vals [$i]['tag']] = $attributes;
				}
				// case where there is an array of identical items with attributes
				elseif (is_array ($children [$vals [$i]['tag']])) {
					$index = count ($children [$vals [$i]['tag']]) - 1;
					// probably also have to check here whether the individual item is also an array or not or what... all a bit messy
					if ($children [$vals [$i]['tag']][$index] == '') {
						unset ($children [$vals [$i]['tag']][$index]);
						$children [$vals [$i]['tag']][$index] = $attributes;
					}
					$children [$vals [$i]['tag']][$index] = array_merge ($children [$vals [$i]['tag']][$index], $attributes);
				} else {
					$value = $children [$vals [$i]['tag']];
					unset ($children [$vals [$i]['tag']]);
					$children [$vals [$i]['tag']]['value'] = $value;
					$children [$vals [$i]['tag']] = array_merge ($children [$vals [$i]['tag']], $attributes);
				}
			} else
				$children [$vals [$i]['tag']] = $attributes;
		}
	}
 
	return $children;
}
 
$url = "http://weather.yahooapis.com/forecastrss?p=USOH0245"; //URL of the XML FEED
 
$contents = file_get_contents($url);
 
$data = GetXMLTree ($contents);
 
$strWeather_Text = $data["rss"]["channel"]["item"]["yweather:condition"]["text"];
$strWeather_Code = $data["rss"]["channel"]["item"]["yweather:condition"]["code"];
$strWeather_Temp = $data["rss"]["channel"]["item"]["yweather:condition"]["temp"];
 
?>
<div>
	<div><? echo $strWeather_Temp; ?>&deg;F</div>
	<div><? echo $strWeather_Text; ?>.</div>
</div>
<div><img src="http://localhost/wapi/images/<? echo $strWeather_Code; ?>.jpg" /></div>
</body>
</html>

Open in new window

0

Featured Post

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
These days socially coordinated efforts have turned into a critical requirement for enterprises.
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question