booky99
booky99

Reputation: 1456

Parse xml array values with node js

I am developing on AWS using Node.js framework. I am grabbing weather data from this XML:

<?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://www.nws.noaa.gov/forecasts/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">2016-08-20T18:44:02Z</creation-date>
    </product>
    <source>
      <more-information>http://www.nws.noaa.gov/forecasts/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.02"/>
    </location>
    <location>
      <location-key>point2</location-key>
      <point latitude="39.70" longitude="-104.80"/>
    </location>
    <location>
      <location-key>point3</location-key>
      <point latitude="47.60" longitude="-122.30"/>
    </location>
    <moreWeatherInformation applicable-location="point1">http://forecast.weather.gov/MapClick.php?textField1=38.99&amp;textField2=-77.02</moreWeatherInformation>
    <moreWeatherInformation applicable-location="point2">http://forecast.weather.gov/MapClick.php?textField1=39.70&amp;textField2=-104.80</moreWeatherInformation>
    <moreWeatherInformation applicable-location="point3">http://forecast.weather.gov/MapClick.php?textField1=47.60&amp;textField2=-122.30</moreWeatherInformation>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-1</layout-key>
      <start-valid-time>2016-08-20T08:00:00-04:00</start-valid-time>
      <end-valid-time>2016-08-20T20:00:00-04:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-2</layout-key>
      <start-valid-time>2016-08-20T20:00:00-04:00</start-valid-time>
      <end-valid-time>2016-08-21T09:00:00-04:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-3</layout-key>
      <start-valid-time>2016-08-20T08:00:00-06:00</start-valid-time>
      <end-valid-time>2016-08-20T20:00:00-06:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-4</layout-key>
      <start-valid-time>2016-08-20T20:00:00-06:00</start-valid-time>
      <end-valid-time>2016-08-21T09:00:00-06:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-5</layout-key>
      <start-valid-time>2016-08-20T08:00:00-07:00</start-valid-time>
      <end-valid-time>2016-08-20T20:00:00-07:00</end-valid-time>
    </time-layout>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n1-6</layout-key>
      <start-valid-time>2016-08-20T20:00:00-07:00</start-valid-time>
      <end-valid-time>2016-08-21T09:00:00-07:00</end-valid-time>
    </time-layout>
    <parameters applicable-location="point1">
      <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n1-1">
        <name>Daily Maximum Temperature</name>
        <value>90</value>
      </temperature>
      <temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n1-2">
        <name>Daily Minimum Temperature</name>
        <value>73</value>
      </temperature>
    </parameters>
    <parameters applicable-location="point2">
      <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n1-3">
        <name>Daily Maximum Temperature</name>
        <value>76</value>
      </temperature>
      <temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n1-4">
        <name>Daily Minimum Temperature</name>
        <value>53</value>
      </temperature>
    </parameters>
    <parameters applicable-location="point3">
      <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n1-5">
        <name>Daily Maximum Temperature</name>
        <value>90</value>
      </temperature>
      <temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n1-6">
        <name>Daily Minimum Temperature</name>
        <value>61</value>
      </temperature>
    </parameters>
  </data>
</dwml>

I have this at the top of my file:

/** module used for parsing XML easily. https://www.npmjs.com/package/xml2js*/
var parseString = require('xml2js').parseString;

Then my main calls this function:

function getNoaa(){
    var baseURL = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php?listLatLon=";

    // Indianapolis
    var originLat = 39.7683800;
    var originLng = -86.1580400;

    // Chicago
    var destLat = 41.881832;
    var destLng = -87.623177;

    baseURL = baseURL.concat(originLat);
    baseURL = baseURL.concat(",");
    baseURL = baseURL.concat(originLng);
    baseURL = baseURL.concat(",");

    baseURL = baseURL.concat(destLat);
    baseURL = baseURL.concat(",");
    baseURL = baseURL.concat(destLng);

    // TIME
    baseURL = baseURL.concat("&product=time-series&begin=2016-08-19T00:00:00&end=2016-08-20T00:00:00");

    // CHARACTERISTICS REQUESTED
    // http://graphical.weather.gov/xml/docs/elementInputNames.php
    baseURL = baseURL.concat("&Unit=e&maxt=maxt&mint=mint&temp=temp&appt=appt&rh=rh");

    console.log(baseURL);

    request(baseURL, function (error, response, body) 
    {
        if (!error && response.statusCode == 200) 
        {
            //console.log(body);

            // parse the XML
            parseString(body, function (err, result) {
                //console.dir(result);

                console.log(result["dwml"]["data"]["location"][1]["point"].latitude);
            });
        }
    })
}

The part thats failing is this line:

console.log(result["dwml"]["data"]["location"][1]["point"].latitude);

This is the error code I get:

2016-08-20T18:37:49.654Z    312eb295-6705-11e6-9e3c-ff815be91875    TypeError: Cannot read property '1' of undefined
    at /var/task/index.js:109:51
    at Parser.<anonymous> (/var/task/node_modules/xml2js/lib/xml2js.js:489:18)
    at emitOne (events.js:77:13)
    at Parser.emit (events.js:169:7)
    at Object.onclosetag (/var/task/node_modules/xml2js/lib/xml2js.js:447:26)
    at emit (/var/task/node_modules/sax/lib/sax.js:640:35)
    at emitNode (/var/task/node_modules/sax/lib/sax.js:645:5)
    at closeTag (/var/task/node_modules/sax/lib/sax.js:905:7)
    at Object.write (/var/task/node_modules/sax/lib/sax.js:1449:13)
    at Parser.exports.Parser.Parser.parseString (/var/task/node_modules/xml2js/lib/xml2js.js:508:31)

I basically want to know what I'm doing wrong with getting the second (or first for that matter) location node inside the data parent node. I want to be able to get the latitude and longitude element values.

Upvotes: 0

Views: 950

Answers (1)

Vincent Sch&#246;ttke
Vincent Sch&#246;ttke

Reputation: 4716

The parsed data from xml2js is not 1 to 1 the same as the xml because in xml it is allowed to have the same name (key) multiple times.

The correct console.log for the second location would be:

console.log(result["dwml"]["data"][0]["location"][1]["point"][0]["$"].latitude);

you can also skip the brackets for the keys:

console.log(result.dwml.data[0].location[1].point[0].$.latitude);

Hope this helps.

Upvotes: 1

Related Questions