Solved

Parsing dynamic external XML file using PHP 4

Posted on 2009-04-08
3
8,937 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

I imagine that there are some, like me, who require a way of getting currency exchange rates for implementation in web project from time to time, so I thought I would share a solution that I have developed for this purpose. It turns out that Yaho…
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

911 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now