Rilcon42
Rilcon42

Reputation: 9763

xml2js is not returning parsed JSON

What am I missing here? The JSON is not being returned from the parseXML method, even though the console.log works correctly. It is returning undefined instead.

function parseXML(){

  var parseString = require('xml2js').parseString;

 var str= '<Customers>\
  <Customer>\
      <first>JIM</first>\
      <last>BEAM</last>\
      <address>22. JIM. RD.</address>\
      <age>24</age>\
      <age2>2.0</age2>\
      <Phone>206-555-0144</Phone>\
  </Customer>\
</Customers>'

parseString(str, function (err, result) {
  console.log(JSON.stringify(result));  //<<<<<<<RETURNS THE JSON I EXPECTED
  return JSON.stringify(result);
});
}

app.get('/*', (request, response) => {
  var json=parseXML();
  console.log(json)     //<<<<<<RETURNS UNDEFINED
  var obj=JSON.parse(json);
  console.log(obj);
  var jsonres= obj.Customers.Customer[0]["first"];

  response.send(['Hello from Express!',jsonres])
})

Upvotes: 0

Views: 934

Answers (2)

Mike
Mike

Reputation: 573

you could make this work with a promise and async / await:

function parseXML() {

var parseString = require('xml2js').parseString;

  var str = '<Customers>\
  <Customer>\
      <first>JIM</first>\
      <last>BEAM</last>\
      <address>22. JIM. RD.</address>\
      <age>24</age>\
      <age2>2.0</age2>\
      <Phone>206-555-0144</Phone>\
  </Customer>\
</Customers>'
return new Promise((resolve, reject) => {
  parseString(str, function (err, result) {
    console.log(JSON.stringify(result));  //<<<<<<<RETURNS THE JSON I EXPECTED
    resolve(JSON.stringify(result))
  });
})
}

app.get('/*', async (request, response) => {
  var json = await parseXML();
  console.log(json)     //<<<<<<RETURNS UNDEFINED
  var obj = JSON.parse(json);
  console.log(obj);
  var jsonres = obj.Customers.Customer[0]["first"];

  response.send(['Hello from Express!', jsonres])
})

EDIT: Sorry I think I should probably add some explanation here.

The parseString function has an asynchronous callback that doesn't fire until the function has finished processing, so the reason your code isn't working is because you are trying to access the data before it's finished processing. here are the steps that are happening:

  1. call parseXML function
  2. call parseString function (this starts the async processing)
  3. try and log the data stored in the json variable, which should be holding the result of the parseXML call. this is undefined because the parseXML function isn't returning anything, so undefined gets logged to the console. Your return value in the parseString callback returns a value from the callback function, not the original function. Furthermore, it doesn't even get called until after you try and access the data in the json variable
  4. the callback function passed to the parseString function completes and you see the the json you expected logged to the console.

My changes basically wrap your parseString in a promise, which resolves when the callback finishes, and return that promise from the parseXML function. This allows you to use async / await to get the result of the async processing. you could alternatively write parseXML().then(data => { //process data here }

Upvotes: 1

Golo Roden
Golo Roden

Reputation: 150892

The problem is that the result of parseString is returned asynchronously, but you don't handle the function call and its result asynchronously.

You might want to look for how asynchronous programming and callbacks work in Node.js and JavaScript.

Upvotes: 1

Related Questions