| (function() { |
| var events, isEmpty, sax; |
| var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; |
| |
| sax = require('sax'); |
| |
| events = require('events'); |
| |
| isEmpty = function(thing) { |
| return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0; |
| }; |
| |
| exports.Parser = (function() { |
| |
| __extends(Parser, events.EventEmitter); |
| |
| function Parser(opts) { |
| this.parseString = __bind(this.parseString, this); |
| this.reset = __bind(this.reset, this); |
| var key, value; |
| this.options = { |
| explicitCharkey: false, |
| trim: true, |
| normalize: true, |
| attrkey: "@", |
| charkey: "#", |
| explicitArray: false, |
| ignoreAttrs: false, |
| mergeAttrs: false |
| }; |
| for (key in opts) { |
| if (!__hasProp.call(opts, key)) continue; |
| value = opts[key]; |
| this.options[key] = value; |
| } |
| this.reset(); |
| } |
| |
| Parser.prototype.reset = function() { |
| var attrkey, charkey, err, stack; |
| var _this = this; |
| this.removeAllListeners(); |
| this.saxParser = sax.parser(true, { |
| trim: false, |
| normalize: false |
| }); |
| err = false; |
| this.saxParser.onerror = function(error) { |
| if (!err) { |
| err = true; |
| return _this.emit("error", error); |
| } |
| }; |
| this.EXPLICIT_CHARKEY = this.options.explicitCharkey; |
| this.resultObject = null; |
| stack = []; |
| attrkey = this.options.attrkey; |
| charkey = this.options.charkey; |
| this.saxParser.onopentag = function(node) { |
| var key, obj, _ref; |
| obj = {}; |
| obj[charkey] = ""; |
| if (!_this.options.ignoreAttrs) { |
| _ref = node.attributes; |
| for (key in _ref) { |
| if (!__hasProp.call(_ref, key)) continue; |
| if (!(attrkey in obj) && !_this.options.mergeAttrs) obj[attrkey] = {}; |
| if (_this.options.mergeAttrs) { |
| obj[key] = node.attributes[key]; |
| } else { |
| obj[attrkey][key] = node.attributes[key]; |
| } |
| } |
| } |
| obj["#name"] = node.name; |
| return stack.push(obj); |
| }; |
| this.saxParser.onclosetag = function() { |
| var nodeName, obj, old, s; |
| obj = stack.pop(); |
| nodeName = obj["#name"]; |
| delete obj["#name"]; |
| s = stack[stack.length - 1]; |
| if (obj[charkey].match(/^\s*$/)) { |
| delete obj[charkey]; |
| } else { |
| if (_this.options.trim) obj[charkey] = obj[charkey].trim(); |
| if (_this.options.normalize) { |
| obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim(); |
| } |
| if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) { |
| obj = obj[charkey]; |
| } |
| } |
| if (_this.options.emptyTag !== void 0 && isEmpty(obj)) { |
| obj = _this.options.emptyTag; |
| } |
| if (stack.length > 0) { |
| if (!_this.options.explicitArray) { |
| if (!(nodeName in s)) { |
| return s[nodeName] = obj; |
| } else if (s[nodeName] instanceof Array) { |
| return s[nodeName].push(obj); |
| } else { |
| old = s[nodeName]; |
| s[nodeName] = [old]; |
| return s[nodeName].push(obj); |
| } |
| } else { |
| if (!(s[nodeName] instanceof Array)) s[nodeName] = []; |
| return s[nodeName].push(obj); |
| } |
| } else { |
| if (_this.options.explicitRoot) { |
| old = obj; |
| obj = {}; |
| obj[nodeName] = old; |
| } |
| _this.resultObject = obj; |
| return _this.emit("end", _this.resultObject); |
| } |
| }; |
| return this.saxParser.ontext = this.saxParser.oncdata = function(text) { |
| var s; |
| s = stack[stack.length - 1]; |
| if (s) return s[charkey] += text; |
| }; |
| }; |
| |
| Parser.prototype.parseString = function(str, cb) { |
| if ((cb != null) && typeof cb === "function") { |
| this.on("end", function(result) { |
| this.reset(); |
| return cb(null, result); |
| }); |
| this.on("error", function(err) { |
| this.reset(); |
| return cb(err); |
| }); |
| } |
| if (str.toString().trim() === '') { |
| this.emit("end", null); |
| return true; |
| } |
| return this.saxParser.write(str.toString()); |
| }; |
| |
| return Parser; |
| |
| })(); |
| |
| }).call(this); |