'How to fetch XML with fetch api
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))
Solution 1:[1]
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:[2]
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:[3]
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:[4]
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);
});
});
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | brc-dd |
Solution 2 | Gilad Artzi |
Solution 3 | Labaguette |
Solution 4 |