Link time-layout element to parameter in NDFD REST API

966 Views Asked by At

I just started to look into the NDFD REST service to get weather data. In short, I don't know how to link a specific parameter to the time-layout element in the return XML.

Example call: http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php?lat=38.99&lon=-77.01&product=time-series&temp=temp&maxt=maxt&mint=mint

I am looking for maximum temperature(maxt), minimum temperature(mint) and 3 hourly temperature (temp) using this call.

The XML I get back is (snipped for relevance):

<?xml version="1.0"?>
<dwml version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
  <head>
    <product srsName="WGS 1984" concise-name="time-series" operational-mode="official">
      <title>NOAA's National Weather Service Forecast Data</title>
      <field>meteorological</field>
      <category>forecast</category>
      <creation-date refresh-frequency="PT1H">2012-12-26T20:03:47Z</creation-date>
    </product>
    <source>
      <more-information>http://graphical.weather.gov/xml/</more-information>
      <production-center>Meteorological Development Laboratory<sub-center>Product Generation Branch</sub-center></production-center>
      <disclaimer>http://www.nws.noaa.gov/disclaimer.html</disclaimer>
      <credit>http://www.weather.gov/</credit>
      <credit-logo>http://www.weather.gov/images/xml_logo.gif</credit-logo>
      <feedback>http://www.weather.gov/feedback.php</feedback>
    </source>
  </head>
  <data>
    <location>
      <location-key>point1</location-key>
      <point latitude="38.99" longitude="-77.01"/>
    </location>
    <moreWeatherInformation applicable-location="point1">http://forecast.weather.gov/MapClick.php?textField1=38.99&amp;textField2=-77.01</moreWeatherInformation>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n7-1</layout-key>
      <start-valid-time>2012-12-26T07:00:00-05:00</start-valid-time>
      <end-valid-time>2012-12-26T19:00:00-05:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n6-2</layout-key>
      <start-valid-time>2012-12-26T19:00:00-05:00</start-valid-time>
      <end-valid-time>2012-12-27T08:00:00-05:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p3h-n34-3</layout-key>
      <start-valid-time>2012-12-26T16:00:00-05:00</start-valid-time>
      <start-valid-time>2012-12-26T19:00:00-05:00</start-valid-time>
      <start-valid-time>2012-12-26T22:00:00-05:00</start-valid-time>
      <start-valid-time>2012-12-27T01:00:00-05:00</start-valid-time>
    </time-layout>
    <parameters applicable-location="point1">
      <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n7-1">
        <name>Daily Maximum Temperature</name>
        <value>34</value>
      </temperature>
      <temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n6-2">
        <name>Daily Minimum Temperature</name>
        <value>34</value>
      </temperature>
      <temperature type="hourly" units="Fahrenheit" time-layout="k-p3h-n34-3">
        <name>Temperature</name>
        <value>33</value>
        <value>34</value>
        <value>34</value>
        <value>34</value>
      </temperature>
    </parameters>
  </data>
</dwml>

Now, I want to link the time-layout element and the child elements of parameters element to maxt, mint and temp so I can populate my model objects accordingly.

Has anyone done something similar to this?

Right now, I am thinking that I can issue 53 service calls (one for each parameter like maxt, mint, temp etc.) but that is not going to scale very well for multiple lat/lon pairs (I have a lot).

I would appreciate any suggestions.

3

There are 3 best solutions below

0
pseudon On

The spec is here: http://www.nws.noaa.gov/mdl/XML/Design/MDL_XML_Design.pdf which you probably have seen. In general, things should line up. In your snippet for example, you have 4 start-valid-time elements, which should correspond to the 4 temperatures. I have noticed that, particularly when it's near the time interval changes, the data may get updated at different times and some elements may be inconsistent or have value xsi:nil="true".

0
Ben Hyde On

Each element includes a layout-key element, that provides the name used to denote that time-layout. Each child of the element has a time-layout attribute, the value of that attribute tells you which time-layout it's aligned with.

Section 5.2 in http://www.nws.noaa.gov/mdl/XML/Design/MDL_XML_Design.pdf_orig is worth reading. Here's an example name: "k-p3h-n28-1" and 5.2 tells us that "k" is for "key, "p3h" is for a period (at least initially) of 3 hours, and that n28 means there are 28 values provides, and finally the -1 is so this will be a unique label. Generally you don't want to parse these labels, just use the actual list of times included in the time-layout element, because the intervals can vary as you move thru the data.

The same scheme is being used to associate locations with the data. The elements have a location-key child which defines a label like "point1" and elements then have a applicable-location attribute to tie them to their location.

0
user1031711 On

I think there are two approaches to this 1) deserializer with a custom class that fits NDFD data result.

you can try the XML Schema Definition Tool (Xsd.exe) at https://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx

2) use LINQ to parse the XML document such as (c#)

System.Xml.Linq.XDocument xmlDoc = System.Xml.Linq.XDocument.Parse(xmlData);

var recordTime = from timevalue in xmlDoc.Descendants("time-layout").Elements("start-valid-time")
                         where timevalue.Parent.Element("layout-key").Value.Contains("k-p3h")
                         select (DateTime)timevalue;

var maxTemperature = from tempvalue in xmlDoc.Descendants("temperature").Elements("value")
                             where tempvalue.Parent.Attribute("type").Value == "maximum"
                          select (double)tempvalue;

var minTemperature = from tempvalue in xmlDoc.Descendants("temperature").Elements("value")
                             where tempvalue.Parent.Attribute("type").Value == "minimum"
                          select (double)tempvalue;

var temperature = from tempvalue in xmlDoc.Descendants("temperature").Elements("value")
                       where tempvalue.Parent.Attribute("type").Value == "hourly"
                       select (double)tempvalue;

var humidity = from humvalue in xmlDoc.Descendants("humidity").Elements("value")
                       where humvalue.Parent.Attribute("type").Value == "relative"
                       select (double)humvalue;