How to fetch XML with fetch api

JavascriptXmlFetch Api

Javascript Problem Overview


I'm trying to making a weather app that displays the weather and the temperature of many days of the week. I'm currently using openweathermap api for such task, the thing is that the information that I want (that is the date of the weather) only comes in xml format. Since I'm rebuilding it in ES6(ES2015) for academic reasons I wanted to also use the fetch api but since the fetch method parses it, it just delivers an error. so how can i fetch it or mby there is a better way to do it.

let apis = {
    currentWeather: { //get user selected recomendation weather
        api:"http://api.openweathermap.org/data/2.5/forecast/daily?lat=",
        parameters: "&mode=xml&units=metric&cnt=6&APPID=/*api key*/",
        url: (lat, lon) => {
            return apis.currentWeather.api + lat + "&lon=" + lon +
                   apis.currentWeather.parameters
        }
    }
};
function getCurrentLoc() { 
    return new Promise((resolve, reject) =>  navigator.geolocation
                                             .getCurrentPosition(resolve, reject))
}
function getCurrentCity(location) {
    const lat = location.coords.latitude;
    const lon = location.coords.longitude;
    return fetch(apis.currentWeather.url(lat, lon))
    .then(response => response.json())
    .then(data => console.log(data))
}
getCurrentLoc()
.then( coords => getCurrentCity(coords))

Javascript Solutions


Solution 1 - Javascript

Using native DOMParser getCurrentCity(location) can be written:

function getCurrentCity(location) {
    const lat = location.coords.latitude;
    const lon = location.coords.longitude;
    return fetch(apis.currentWeather.url(lat, lon))
        .then(response => response.text())
        .then(str => new window.DOMParser().parseFromString(str, "text/xml"))
        .then(data => console.log(data));
}

Solution 2 - Javascript

I guess the error is coming from this function: response => response.json() since the response is not a valid JSON object (it's XML).

As far as I know, there is no native XML parser for fetch, but you can handle the response as text and use a third party tool to do the actual parsing, for example jQuery has a $.parseXML() function.

It will look something like:

function getCurrentCity(location) {
    const lat = location.coords.latitude;
    const lon = location.coords.longitude;
    return fetch(apis.currentWeather.url(lat, lon))
        .then(response => response.text())
        .then(xmlString => $.parseXML(xmlString))
        .then(data => console.log(data))
}

Solution 3 - Javascript

It is possible to use the npm xml-js library and node-fetch to do this in Node.js, for those who want to test this out in the Node REPL.

First off we install the two modules xml-js and node-fetch with:

> npm install xml-js --save > npm install node-fetch --save

to store these two packages into package.json. Now over to our problem at hand - how to work with XML data returned from an API.

Consider the following example fetching a particular weather station in Norway:

const fetch = require('node-fetch');
const convert = require('xml-js');
let dataAsJson = {};

fetch('http://eklima.met.no/metdata/MetDataService?invoke=getStationsProperties&stations=68050&username=')
    .then(response => response.text())
    .then(str => {
        dataAsJson = JSON.parse(convert.xml2json(str))
    })
    .then(() => {
        console.log('Station id returned from the WS is:' + 
            `${dataAsJson.elements[0].elements[0].elements[0].elements[0].elements[0].elements
                .filter(obj => { return obj.name == 'stnr'; })[0].elements[0].text} Expecting 68050 here!`
        );
    });

We now have got a variable that is actually parsed into a JSON object from the XML data using convert's xml2json method and using JSON.parse. If we want to print out the object, we can use JSON.stringify to turn the JSON object into a string. The retrieval of the station id in this code just shows the need to scan through an object graph deep for a given key, since turning XML into Json gives often even deeper object graphs, since the wrapping XML elements are always at the top of the "XML object JSON-graph". There are some tips around deep searching object graphs that are deep to look for a key, like obj-traverse library on GitHub

Solution 4 - Javascript

This worked in my angular app

import * as xml2js from 'xml2js';

url = MY_URL;

ngOnInit(): void {
 this.getData();
}

getData(): void {
  fetch(MY_URL)
    .then(response => response.text())
    .then(data => {
      let parseString = xml2js.parseString;
      parseString(data, function (err, result) {
        console.log(result);
        console.error(err);
      });
    });
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTrip1View Question on Stackoverflow
Solution 1 - JavascriptJukkaPView Answer on Stackoverflow
Solution 2 - JavascriptGilad ArtziView Answer on Stackoverflow
Solution 3 - JavascriptTore AurstadView Answer on Stackoverflow
Solution 4 - JavascriptDrony QualwebsView Answer on Stackoverflow