Solved

Parsing dynamic external XML file using PHP 4

Posted on 2009-04-08
3
8,951 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

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

Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn how to dynamically set the form action using jQuery.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

622 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