More Examples with Parsing NDFD Data in PHP

Published: March 3rd, 2009 by:

I covered how to Parse Weather Forecast Data (from the NDFD) in PHP in a previous article, but due to the amount of questions I received, I decided to show some more usage techniques and examples. In this article, I will cover the time-series option as well as some methods on how to make some data more presentable.


Fetching Time-Series Data from the NDFD

This was covered as an appendix in the previous article, but I will include it here as well in case you are only reading it in the feeds or by email.

Requesting the time-series data returns a whole bunch more information. As requested, here is an example on how to fetch it. Change the desired parameters to ‘true’. The other examples on how to parse the time layouts and formatting data works on this XML, too.

Run This Example

<?php

/* http://sourceforge.net/projects/nusoap/ */
require('../includes/nusoap/nusoap.php');

$parameters = array('product'	=> 'time-series',
					'latitude'  => 41.879535,
					'longitude'	=> -87.624333,
					'weatherParameters' => array(
					
	'maxt' => true,			'mint' => false,		'temp' => false,			'dew' => false,	
	'appt' => true,			'pop12' => false,		'qpf' => false,				'snow' => false,	
	'sky' => false,			'rh' => false,			'wspd' => false,			'wdir' => false,	
	'wx' => false,			'icons' => false,		'waveh' => false,			'incw34' => false,	
	'incw50' => false,		'incw64' => false,		'cumw34' => false,			'cumw50' => false,	
	'cumw64' => false,		'wgust' => false,		'conhazo' => false,			'ptornado' => false,	
	'phail' => false,		'ptstmwinds' => false,	'pxtornado' => false,		'pxhail' => false,	
	'pxtstmwinds' => false,	'ptotsvrtstm' => false,	'pxtotsvrtstm' => false,	'tmpabv14d' => false,	
	'tmpblw14d' => false,	'tmpabv30d' => false,	'tmpblw30d' => false,		'tmpabv90d' => false,	
	'tmpblw90d' => false,	'prcpabv14d' => false,	'prcpblw14d' => false,		'prcpabv30d' => false,	
	'prcpblw30d' => false,	'prcpabv90d' => false,	'prcpblw90d' => false,		'precipa_r' => false,	
	'sky_r' => false,		'td_r' => false,		'temp_r' => false,			'wdir_r' => false,	
	'wwa' => false,			'wspd_r' => false)
	
					);

try
{
	/* create the nuSOAP object */
	$c = new nusoap_client('http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl', 'wsdl');
	
	/* make the request */
	$result = $c->call('NDFDgen', $parameters);
}
catch (Exception $ex)
{
	/* nuSOAP throws an exception is there was a problem fetching the data */
	echo 'failed';
}

header('Content-type: text/xml');
echo $result;

/* ?> */

Merging Sets of Data with Different Time Layouts

The different sets of data in the NDFD are most likely going to be wanted to be displayed together. For example, on this page, you will see that I have the conditions icons, max temps, and min temps all showing at the same time intervals. But how is that possible?

In this example case, we are going to match up the high temperatures with their conditions icon. This may not give an accurate weather condition for the day because we are going to pick the icon that is the closest to the time stamp given for that temperature. In other words, the condition icons are for every hour or so, and the temperatures are only twice a day. We have to pick two of those icons to match up with the two temperatures. So for example, if the forecast for the day is “sunny in the morning, then t’storms in the afternoon”, the icon will show up as sunny.

Run This Example

<?php

/* returns the next element based on the key provided */
function array_next($array, $key, $offset = 0)
{
	/* if the key exists, we're done */
	if (isset($array[$key]) && $offset == 0) return $array[$key];
	
	/* insert the key into the array and sort it */
	$array[$key] = 1;
	ksort($array);
	
	/* now get the array in order */
	$keys = array_keys($array);
	
	/* find where our inserted key is and get the next element */
	$index = array_search($key, $keys);
	if ($offset == 0) $offset = 1;
	$index += $offset;
	return (isset($keys[$index])) ? $array[$keys[$index]] : FALSE;
}

/**
 * load the forecast data array as produced in the below example:
 * http://phpstarter.net/samples/348/parse_data.php
 * More information:
 * http://phpstarter.net/2009/02/parse-weather-forecast-data-from-the-ndfd-in-php/
 */
include('parse_data.php');
$forecast = parse_data();

?>
<html>
<head><title>NDFD Usage Example w/ Different Time Layouts</title></head>
<body>
<h1>Show High Temps with Icons</h1>
<?php foreach ($forecast['max_temps'] as $timestamp => $temp): ?>
<p><?=$field?><br />
<img src="<?=array_next($forecast['icons'], $timestamp)?>" /><br />
High: <?=$temp?></p>
<?php endforeach; ?>
</body>
</html>

In the above example, the array_next() function is the one that allows us to match up the data arrays. The first parameter is the array of the weather data that we are trying to find…or in our case, the conditions icon. The second parameter is the key that we want to get close to…or in our case, the timestamp for the temperature we are displaying. So, we loop through the temperatures and search for the closest icon for each one.

Collecting and Using the Time Labels

Depending on that kind of data you are requesting, some of the time layouts contain the time labels. I had those time labels displayed in a data array called time_labels in a previous example, but I didn’t explain how I did it. Basically, I wrote a function that sifts through all of the time layouts. If it finds one with a “period-name” attribute, it saves that timestamp and the period name in a data array similar to the other data items (temp, conditions, etc).

Run This Example

<?php

/**
 * get the time layouts in an array form
 * 
 * @param string $xml
 * @return mixed
 */
function get_time_labels($xml)
{
	$data = $xml->xpath("//start-valid-time");
	$times = array();
	
	foreach ($data as $field => $value)
	{
		if ((string)$value['period-name'])
		{
			$index = (string)$value;
			$times[$index] = (string)$value['period-name'];
		}
	}
	
	ksort($times);
	
	return $times;
}

/* working with stale data, but why query for it every time */
$xml = file_get_contents('ndfd_forecast.xml');
$xml = new SimpleXMLElement($xml);

$time_labels = get_time_labels($xml);

header('Content-type: text/plain');
var_dump($time_labels);

/**
 * Why do I comment out the PHP closing tag?
 * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/
 */
/* ?> */

We can apply it with the Merging Sets of Data example, and end up with something like this:

Run This Example

<?php

/* returns the next element based on the key provided */
function array_next($array, $key, $offset = 0)
{
	/* if the key exists, we're done */
	if (isset($array[$key]) && $offset == 0) return $array[$key];
	
	/* insert the key into the array and sort it */
	$array[$key] = 1;
	ksort($array);
	
	/* now get the array in order */
	$keys = array_keys($array);
	
	/* find where our inserted key is and get the next element */
	$index = array_search($key, $keys);
	if ($offset == 0) $offset = 1;
	$index += $offset;
	return (isset($keys[$index])) ? $array[$keys[$index]] : FALSE;
}

/**
 * load the forecast data array as produced in the below example:
 * http://phpstarter.net/samples/348/parse_data.php
 * More information:
 * http://phpstarter.net/2009/02/parse-weather-forecast-data-from-the-ndfd-in-php/
 */
include('parse_data.php');
$forecast = parse_data();

?>
<html>
<head><title>Show Condition Icons with Time Labels</title></head>
<body>
<h1>Show Condition Icons with Time Labels</h1>
<?php foreach ($forecast['time_labels'] as $timestamp => $label): ?>
<p><?=$label?><br />
<img src="<?=array_next($forecast['icons'], $timestamp)?>" /></p>
<?php endforeach; ?>
</body>
</html>

So there you have it – more possible applications and examples with this abundant weather forecast data. As with all other advanced articles on phpstarter.net, this is not intended provide you with copy-and-paste code to paste right in your web applications with little or no modifications. You really need to understand how this all works, and adapt it as necessary or rewrite the examples completely based on what you learned here and what you need to use it for. The point is to get you to understand the concepts used here so you can apply them to your web applications. Happy coding! 🙂


17 Responses to “More Examples with Parsing NDFD Data in PHP”

  • Sam

    Andrew,
    Thanks for this. I’ve been rummaging through php parsing ideas for the past few days and this shed some new light on the matter. I have a few questions for you: Where does this function come from: parse_data();(line 30 in last code example)? The other is related to the wx field. I’ve been trying to set the timecode as key for the wx attrbutes. I keep getting an error because there is one more element in the array of attributes than the time-code total elements. I counted them both with php and on my fingers and it’s true. Have you run into this? If so how did you deal with it?
    Cheers,
    Sam

     

  • Sam

    Just to follow up on the wx parameter question, it turns out that the first two elements each have two nodes… not sure what to make of it or how to proceed, but it explains the problem! Thoughts?

     

  • Andrew

    Hi Sam, The parse_data() is just a function I put together to include the code from this example. No point in including that code again if I already explained it. 🙂

    Which data sets don’t line up with their respective time layouts? I’ve never had that problem.

     

  • Sam

    Hey Andrew,
    Should have caught that! Spitting out questions before asking. Makes perfect sense.

    The data sets I’m dealing with are the wx parameter. Here is an example of an element:

            Weather Type, Coverage, and Intensity
            
              
                
              

    2 issues: trying to implode the element attributes to read something like ‘scattered light snow showers’ and then put that string in an array with the corresponding timestamp key. The second issue is that sometimes the sometimes contains two elements and sometimes is totally empty. I think this is causing the false alignment in the array combine.
    Thoughts?

     

  • Sam

    (trid wrapping the code in xml code tags. here is another attempt:

    Weather Type, Coverage, and Intensity

     

  • Sam

    hmmm one more time? (changed the tags again. Obviously this is NOT how the XML would be written)

    weather time-layout=”k-p1h-n51-6″
    >namenameweather-conditionsvalue coverage=”scattered” intensity=”light” weather-type=”snow showers” qualifier=”none”visibility xsi:nil=”true”//value<

     

  • Andrew

    In this sample XML file, I counted 35 entries for the “Weather Type, Coverage, and Intensity” data and the time layout that it uses, so everything seems correct there.

    I think you’re right, there is probably a mis-alignment because some of the elements are empty (no rain/snow/etc present). You will just have to test for that emptiness on each one.

    It has two or more elements when there is an element of uncertainty. For example, on one of them, it shows rain or snow, because it could be either.

    On a side note, it looks like WordPress is filtering tags from the comments. I will have to look into a way of disabling that, because I want people to be able to post code here.

     

  • Sam

    Andrew,
    Have you been able to successfully parse the wx parameter? I’m still failing miserably!
    Sam

     

  • Sam

    just to update:
    I was able to put the wx parameter data into an array using this code:

    $wxstr = $xml-&gt;data-&gt;parameters-&gt;weather-&gt;{'weather-conditions'};
    		foreach (get_wxvalues($wxstr) as $node){
    		        $attr1 = $node-&gt;value['coverage'];
    			$attr2 = $node-&gt;value['intensity'];
    			$attr3 = $node-&gt;value['weather-type'];
    			$atts =  $attr1 ." ". $attr2 ." ". $attr3;
    			$combine[] =$atts;
    		}	
    

    using andrew’s code you can then easily combine arrays with time-layout as key! i don’t know if this is the best way to do it, but it worked for me!

     

  • Andrew

    Hey Sam, glad to hear you got it. Good luck with the rest of your application!

     

  • Carl

    Sam what does your get_wxvalues function look like-sorry just learning

     

  • cloud9ine

    Andrew,

    Using NDFD Weather data to arrive at a simple daily kind of forecast seems a very tedious process. Is there some kind of SOAP / XML service which would provide just this information?

    For example, is there a way to get information that represents the “Forecast at a Glance” and “Current Conditions” boxes on http://forecast.weather.gov/MapClick.php?CityName=Florissant&state=MO&site=LSX&textField1=38.7974&textField2=-90.3243

    This is especially important when you are trying to pick up data and represent elements in enumerated data types for ease of representation and decoding for a remote small embedded device.

    Are you aware of any such sources I could use? Any help is appreciated. Thanks.

     

  • Andrew

    cloud9ine:

    The NDFD data is what I use for something like the “Forecast at a Glance”, as shown in this example. See this page, which is a site I made using this example.

    Also, for the current conditions box, see this article: Parse Current Weather Conditions Data from the NWS in PHP

     

  • Nick

    Thanks for the helpful code. Is there is simple way to extract the hourly weather forecast? Do you know if it is possible to got more weather data than every 3 hours?

    Thanks!

     

  • Roch

    Hi! I saw the wx parameter on this page and its exactly what I need.  But that piece of code isn’t working for me.  Has anyone gotten this to work?

     

  • Ron

    Hello Andrew

    I have been “playing” with your scripts for the last few days. My question for you is; I cannot find any where is the scripts that have eithe echo or print. On the screen displays the data in arrays and I was able to display the max temp with the condition icons. The array still is displayed.

    Can you explain to me how this data prints to the screen?    

     

  • Andrew

    Hi Ron – The sections that show the variable structure are printing by using the var_dump() function.

     

Leave a Reply





Wordpress doesn't like it when you post PHP code. Go save your code at pastebin, and post the link here.

About the Author

Andrew has been coding PHP applications since 2006, and has plenty of experience with PHP, MySQL, and Apache. He prefers Ubuntu Linux on his desktop and has plenty of experience at managing CentOS web servers. He is the owner of Wells IT Solutions LLC, and develops PHP applications full time for anyone that needs it as well as does desktop computer support locally in the local area. He spends most of his free time exploring new programming concepts and posting on The Webmaster Forums.