Improve company productivity with a Business Account.Sign Up

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 8962
  • Last Modified:

Parsing dynamic external XML file using PHP 4

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:

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="" xmlns:geo="" version="2.0">
		<title>Yahoo! Weather - Dayton, OH</title>
		<description>Yahoo! Weather for Dayton, OH</description>
		<lastBuildDate>Wed, 08 Apr 2009 12:56 pm EDT</lastBuildDate>
		<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"/>
			<title>Yahoo! Weather</title>
			<title>Conditions for Dayton, OH at 12:56 pm EDT</title>
			<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"/>
				<![CDATA[<img src=""/><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="*">Full Forecast at Yahoo! Weather</a><BR/>
					(provided by The Weather Channel)<br/>]]>
			<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>
<!-- uncompressed Wed Apr  8 10:54:56 PDT 2009 -->

Open in new window

  • 2
2 Solutions
Thomas WheelerCommented:
you should use something like this rss_reader class
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;
      case 'LINK':
        $this->link = true;
      case 'DESCRIPTION':
        $this->description = true;
       case 'DC:DATE':
        $this->date = true;
  function endElement( $parser, $tagName ) {
    switch( $tagName ) {
                case 'DC:DATE':
                                $this->tmp[0] = $this->strdate;
                        $this->date = false;
                        $this->strdate = "";
      case 'TITLE':
                        $this->tmp[1] = $this->titletext;
        $this->title = false;
        $this->titletext = "";
      case 'LINK':
                        $this->tmp[2] = $this->linktext;
        $this->link = false;
        $this->linktext = "";
      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//
  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

BGHTechGuruAuthor Commented:
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?
BGHTechGuruAuthor Commented:
Actually, I found a solution a little bit ago.

I used this script from Whoooop:

Here is the code that worked:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<html xmlns="">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Weather Widget</title>
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']);
			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 = ""; //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><? echo $strWeather_Temp; ?>&deg;F</div>
	<div><? echo $strWeather_Text; ?>.</div>
<div><img src="http://localhost/wapi/images/<? echo $strWeather_Code; ?>.jpg" /></div>

Open in new window

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now