Jump To …

responseparser.js

var xml2js = require('../vendor/node-xml2js/lib/xml2js'),
	underscore = require('underscore');

Tidies up and optionally parses the XML API response

The options argument should contain the following properties:

  • format - The desired response format
  • logger - An instance of {Winston.Logger} for output

  • @param {Object} options

  • @constructor
function ResponseParser(options) {
	this.format = options.format;
	this.logger = options.logger;
}

The API returns resources as either a single object or an array. This makes responses fiddly to deal with for consumers as they manually check whether the resource has a length an access the property appropriately. This method checks for an object and wraps it in an array if it is.

  • @param {Object} response
  • @return {Object} the normalised response
ResponseParser.prototype.normaliseResourceArrays = function (response) {
	underscore([
			'tracks.track',
			'artists.artist',
			'chart.chartItem',
			'releases.release',
			'searchResult.artist',
			'recommendations.recommendedItem',
			'searchResult.release',
			'tags.tag',
			'taggedResults.taggedItem',
			'basketItems.basketItem'
		]).each(function checkLength(item) {
			var parts = item.split('.'),
				parent = parts[0],
				child = parts[1];

			if (response[parent] && response[parent][child] &&
				!response[parent][child].length) {
				response[parent][child] = [response[parent][child]];
			}
		});

	return response;
};

Callback for parsing the XML response return from the API and converting it to JSON and handing control back to the caller.

  • @param {Function} callback - the caller's callback
  • @param {String} response - the XML response from the API
ResponseParser.prototype.parse = function (callback, err, response) {
	var parser,
		self = this;

	if (err) {
		callback(err);
		return;
	}

	if (this.format.toUpperCase() === 'XML') {
		callback(null, response);
		return;
	}

	parser = new xml2js.Parser();

Check the request was authorised

	if (response.statusCode === 401) {
		callback(response);
		return;
	}

	this.logger.silly(response);
	this.logger.info('Parsing XML response from API');
	parser.on('end', function (result) {

Manually remove the xml namespace bits

		delete result['xmlns:xsi'];
		delete result['xsi:noNamespaceSchemaLocation'];

		if (result.status === 'error') {
			callback(result.error);
		}
		else {
			var normalisedResult = self.normaliseResourceArrays(result);
			callback(null, normalisedResult);
		}
	});

	parser.parseString(response + '');
};

module.exports = ResponseParser;