226 lines
6.3 KiB
JavaScript
226 lines
6.3 KiB
JavaScript
// Generated by CoffeeScript 1.3.1
|
|
(function() {
|
|
var events, isEmpty, sax,
|
|
__hasProp = {}.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; },
|
|
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
|
|
|
sax = require('sax');
|
|
|
|
events = require('events');
|
|
|
|
isEmpty = function(thing) {
|
|
return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
|
|
};
|
|
|
|
exports.defaults = {
|
|
"0.1": {
|
|
explicitCharkey: false,
|
|
trim: true,
|
|
normalize: true,
|
|
attrkey: "@",
|
|
charkey: "#",
|
|
explicitArray: false,
|
|
ignoreAttrs: false,
|
|
mergeAttrs: false,
|
|
explicitRoot: false,
|
|
validator: null
|
|
},
|
|
"0.2": {
|
|
explicitCharkey: false,
|
|
trim: false,
|
|
normalize: false,
|
|
attrkey: "$",
|
|
charkey: "_",
|
|
explicitArray: true,
|
|
ignoreAttrs: false,
|
|
mergeAttrs: false,
|
|
explicitRoot: true,
|
|
validator: null
|
|
}
|
|
};
|
|
|
|
exports.ValidationError = (function(_super) {
|
|
|
|
__extends(ValidationError, _super);
|
|
|
|
ValidationError.name = 'ValidationError';
|
|
|
|
function ValidationError(message) {
|
|
this.message = message;
|
|
}
|
|
|
|
return ValidationError;
|
|
|
|
})(Error);
|
|
|
|
exports.Parser = (function(_super) {
|
|
|
|
__extends(Parser, _super);
|
|
|
|
Parser.name = 'Parser';
|
|
|
|
function Parser(opts) {
|
|
this.parseString = __bind(this.parseString, this);
|
|
|
|
this.reset = __bind(this.reset, this);
|
|
|
|
var key, value, _ref;
|
|
this.options = {};
|
|
_ref = exports.defaults["0.1"];
|
|
for (key in _ref) {
|
|
if (!__hasProp.call(_ref, key)) continue;
|
|
value = _ref[key];
|
|
this.options[key] = value;
|
|
}
|
|
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,
|
|
_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 node, nodeName, obj, old, s, xpath;
|
|
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 (_this.options.validator != null) {
|
|
xpath = "/" + ((function() {
|
|
var _i, _len, _results;
|
|
_results = [];
|
|
for (_i = 0, _len = stack.length; _i < _len; _i++) {
|
|
node = stack[_i];
|
|
_results.push(node["#name"]);
|
|
}
|
|
return _results;
|
|
})()).concat(nodeName).join("/");
|
|
obj = _this.options.validator(xpath, s && s[nodeName], obj);
|
|
}
|
|
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;
|
|
}
|
|
try {
|
|
return this.saxParser.write(str.toString());
|
|
} catch (ex) {
|
|
if (ex instanceof exports.ValidationError) {
|
|
return this.emit("error", ex.message);
|
|
} else {
|
|
throw ex;
|
|
}
|
|
}
|
|
};
|
|
|
|
return Parser;
|
|
|
|
})(events.EventEmitter);
|
|
|
|
}).call(this);
|