booky99 booky99 - 3 months ago 12
Javascript Question

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.

Answer

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.