betfair-sports-api
Version:
Betfair Sports API for Node
140 lines (116 loc) • 3.44 kB
JavaScript
// (C) 2012 Anton Zemlyanov
//
// Emulator allows test bots for "free" using real price data
//
var EasySAXParser = require('easysax');
var util = require('util');
exports.decode = function(xml, schema) {
// parse XML
var parser = new RequestParser();
var result = parser.parse(xml);
return result;
}
function RequestParser() {
var self = this;
self.capture = false;
self.current = new XmlNode('request', {});
self.current.ref = {};
self.stack = [ self.current ];
}
RequestParser.prototype.parse = function(xml) {
var self = this;
var parser = new EasySAXParser();
// error during parse
parser.on('error', function(err) {
// error
return {
error : err
};
});
// tag opened
parser.on('startNode', function(node, attr, uq) {
// console.log("open node", node);
var attrs = attr();
if (node === 'soap:Fault') {
return {
error : "SOAP Fault"
};
} else if (node === 'request') {
// console.log('start XML capture');
self.capture = true;
} else if (self.capture === true) {
++self.current.children;
var xmlNode = new XmlNode(node, attrs);
xmlNode.parent = self.current;
self.stack.push(xmlNode);
self.current = xmlNode;
}
});
// tag closed
parser.on('endNode', function(node, uq) {
// console.log("close node", node);
if (node === 'request') {
// console.log('stop XML capture');
self.capture = false;
} else if (self.capture) {
var current = self.stack.pop(); // drop current element
var parent = self.stack[self.stack.length - 1];
if (current.type === 'date')
current.fixDate();
parent.type === 'array' ? parent.ref.push(current.ref)
: parent.ref[current.tagName] = current.ref;
self.current = parent;
}
});
// tag text
parser.on('textNode', function(text, uq) {
// is whitespace?
if (text.replace(/\s/g, '') === "")
return;
if (typeof (self.current.ref) !== 'string')
self.current.ref = text;
else
self.current.ref += text;
});
// do parsing
try {
parser.parse(xml);
} catch (ex) {
return {
error : ex.message
};
}
return self.current.ref;
}
function XmlNode(name, attrs) {
var self = this;
// node info
self.tagName = name;
self.text = '';
self.children = 0;
self.parent = null;
// guess node type and fill ref. Can be changed later
var xsitype = attrs['xsi:type'];
var xsinil = attrs['xsi:nil'];
if (xsitype && xsitype === 'xsd:string') {
self.type = 'string';
self.ref = '';
} else if (xsitype && xsitype === 'xsd:dateTime') {
self.type = 'date';
self.ref = null;
} else if (xsitype && xsitype.indexOf('ArrayOf') >= 0) {
self.type = 'array';
self.ref = [];
} else if (xsinil) {
self.type = 'nil';
self.ref = null;
} else {
self.type = 'object';
self.ref = {};
}
}
XmlNode.prototype.fixDate = function() {
var self = this;
if (self.type === 'date')
self.ref = new Date(self.ref);
}