You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
12 KiB
JavaScript
358 lines
12 KiB
JavaScript
6 years ago
|
// Generated by CoffeeScript 1.12.7
|
||
|
(function() {
|
||
|
"use strict";
|
||
|
var bom, defaults, events, isEmpty, processItem, processors, sax, setImmediate,
|
||
|
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||
|
extend = 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; },
|
||
|
hasProp = {}.hasOwnProperty;
|
||
|
|
||
|
sax = require('sax');
|
||
|
|
||
|
events = require('events');
|
||
|
|
||
|
bom = require('./bom');
|
||
|
|
||
|
processors = require('./processors');
|
||
|
|
||
|
setImmediate = require('timers').setImmediate;
|
||
|
|
||
|
defaults = require('./defaults').defaults;
|
||
|
|
||
|
isEmpty = function(thing) {
|
||
|
return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
|
||
|
};
|
||
|
|
||
|
processItem = function(processors, item, key) {
|
||
|
var i, len, process;
|
||
|
for (i = 0, len = processors.length; i < len; i++) {
|
||
|
process = processors[i];
|
||
|
item = process(item, key);
|
||
|
}
|
||
|
return item;
|
||
|
};
|
||
|
|
||
|
exports.Parser = (function(superClass) {
|
||
|
extend(Parser, superClass);
|
||
|
|
||
|
function Parser(opts) {
|
||
|
this.parseString = bind(this.parseString, this);
|
||
|
this.reset = bind(this.reset, this);
|
||
|
this.assignOrPush = bind(this.assignOrPush, this);
|
||
|
this.processAsync = bind(this.processAsync, this);
|
||
|
var key, ref, value;
|
||
|
if (!(this instanceof exports.Parser)) {
|
||
|
return new exports.Parser(opts);
|
||
|
}
|
||
|
this.options = {};
|
||
|
ref = defaults["0.2"];
|
||
|
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;
|
||
|
}
|
||
|
if (this.options.xmlns) {
|
||
|
this.options.xmlnskey = this.options.attrkey + "ns";
|
||
|
}
|
||
|
if (this.options.normalizeTags) {
|
||
|
if (!this.options.tagNameProcessors) {
|
||
|
this.options.tagNameProcessors = [];
|
||
|
}
|
||
|
this.options.tagNameProcessors.unshift(processors.normalize);
|
||
|
}
|
||
|
this.reset();
|
||
|
}
|
||
|
|
||
|
Parser.prototype.processAsync = function() {
|
||
|
var chunk, err;
|
||
|
try {
|
||
|
if (this.remaining.length <= this.options.chunkSize) {
|
||
|
chunk = this.remaining;
|
||
|
this.remaining = '';
|
||
|
this.saxParser = this.saxParser.write(chunk);
|
||
|
return this.saxParser.close();
|
||
|
} else {
|
||
|
chunk = this.remaining.substr(0, this.options.chunkSize);
|
||
|
this.remaining = this.remaining.substr(this.options.chunkSize, this.remaining.length);
|
||
|
this.saxParser = this.saxParser.write(chunk);
|
||
|
return setImmediate(this.processAsync);
|
||
|
}
|
||
|
} catch (error1) {
|
||
|
err = error1;
|
||
|
if (!this.saxParser.errThrown) {
|
||
|
this.saxParser.errThrown = true;
|
||
|
return this.emit(err);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Parser.prototype.assignOrPush = function(obj, key, newValue) {
|
||
|
if (!(key in obj)) {
|
||
|
if (!this.options.explicitArray) {
|
||
|
return obj[key] = newValue;
|
||
|
} else {
|
||
|
return obj[key] = [newValue];
|
||
|
}
|
||
|
} else {
|
||
|
if (!(obj[key] instanceof Array)) {
|
||
|
obj[key] = [obj[key]];
|
||
|
}
|
||
|
return obj[key].push(newValue);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Parser.prototype.reset = function() {
|
||
|
var attrkey, charkey, ontext, stack;
|
||
|
this.removeAllListeners();
|
||
|
this.saxParser = sax.parser(this.options.strict, {
|
||
|
trim: false,
|
||
|
normalize: false,
|
||
|
xmlns: this.options.xmlns
|
||
|
});
|
||
|
this.saxParser.errThrown = false;
|
||
|
this.saxParser.onerror = (function(_this) {
|
||
|
return function(error) {
|
||
|
_this.saxParser.resume();
|
||
|
if (!_this.saxParser.errThrown) {
|
||
|
_this.saxParser.errThrown = true;
|
||
|
return _this.emit("error", error);
|
||
|
}
|
||
|
};
|
||
|
})(this);
|
||
|
this.saxParser.onend = (function(_this) {
|
||
|
return function() {
|
||
|
if (!_this.saxParser.ended) {
|
||
|
_this.saxParser.ended = true;
|
||
|
return _this.emit("end", _this.resultObject);
|
||
|
}
|
||
|
};
|
||
|
})(this);
|
||
|
this.saxParser.ended = false;
|
||
|
this.EXPLICIT_CHARKEY = this.options.explicitCharkey;
|
||
|
this.resultObject = null;
|
||
|
stack = [];
|
||
|
attrkey = this.options.attrkey;
|
||
|
charkey = this.options.charkey;
|
||
|
this.saxParser.onopentag = (function(_this) {
|
||
|
return function(node) {
|
||
|
var key, newValue, obj, processedKey, 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] = {};
|
||
|
}
|
||
|
newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key];
|
||
|
processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key;
|
||
|
if (_this.options.mergeAttrs) {
|
||
|
_this.assignOrPush(obj, processedKey, newValue);
|
||
|
} else {
|
||
|
obj[attrkey][processedKey] = newValue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
obj["#name"] = _this.options.tagNameProcessors ? processItem(_this.options.tagNameProcessors, node.name) : node.name;
|
||
|
if (_this.options.xmlns) {
|
||
|
obj[_this.options.xmlnskey] = {
|
||
|
uri: node.uri,
|
||
|
local: node.local
|
||
|
};
|
||
|
}
|
||
|
return stack.push(obj);
|
||
|
};
|
||
|
})(this);
|
||
|
this.saxParser.onclosetag = (function(_this) {
|
||
|
return function() {
|
||
|
var cdata, emptyStr, key, node, nodeName, obj, objClone, old, s, xpath;
|
||
|
obj = stack.pop();
|
||
|
nodeName = obj["#name"];
|
||
|
if (!_this.options.explicitChildren || !_this.options.preserveChildrenOrder) {
|
||
|
delete obj["#name"];
|
||
|
}
|
||
|
if (obj.cdata === true) {
|
||
|
cdata = obj.cdata;
|
||
|
delete obj.cdata;
|
||
|
}
|
||
|
s = stack[stack.length - 1];
|
||
|
if (obj[charkey].match(/^\s*$/) && !cdata) {
|
||
|
emptyStr = obj[charkey];
|
||
|
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();
|
||
|
}
|
||
|
obj[charkey] = _this.options.valueProcessors ? processItem(_this.options.valueProcessors, obj[charkey], nodeName) : obj[charkey];
|
||
|
if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
|
||
|
obj = obj[charkey];
|
||
|
}
|
||
|
}
|
||
|
if (isEmpty(obj)) {
|
||
|
obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr;
|
||
|
}
|
||
|
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("/");
|
||
|
(function() {
|
||
|
var err;
|
||
|
try {
|
||
|
return obj = _this.options.validator(xpath, s && s[nodeName], obj);
|
||
|
} catch (error1) {
|
||
|
err = error1;
|
||
|
return _this.emit("error", err);
|
||
|
}
|
||
|
})();
|
||
|
}
|
||
|
if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') {
|
||
|
if (!_this.options.preserveChildrenOrder) {
|
||
|
node = {};
|
||
|
if (_this.options.attrkey in obj) {
|
||
|
node[_this.options.attrkey] = obj[_this.options.attrkey];
|
||
|
delete obj[_this.options.attrkey];
|
||
|
}
|
||
|
if (!_this.options.charsAsChildren && _this.options.charkey in obj) {
|
||
|
node[_this.options.charkey] = obj[_this.options.charkey];
|
||
|
delete obj[_this.options.charkey];
|
||
|
}
|
||
|
if (Object.getOwnPropertyNames(obj).length > 0) {
|
||
|
node[_this.options.childkey] = obj;
|
||
|
}
|
||
|
obj = node;
|
||
|
} else if (s) {
|
||
|
s[_this.options.childkey] = s[_this.options.childkey] || [];
|
||
|
objClone = {};
|
||
|
for (key in obj) {
|
||
|
if (!hasProp.call(obj, key)) continue;
|
||
|
objClone[key] = obj[key];
|
||
|
}
|
||
|
s[_this.options.childkey].push(objClone);
|
||
|
delete obj["#name"];
|
||
|
if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
|
||
|
obj = obj[charkey];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (stack.length > 0) {
|
||
|
return _this.assignOrPush(s, nodeName, obj);
|
||
|
} else {
|
||
|
if (_this.options.explicitRoot) {
|
||
|
old = obj;
|
||
|
obj = {};
|
||
|
obj[nodeName] = old;
|
||
|
}
|
||
|
_this.resultObject = obj;
|
||
|
_this.saxParser.ended = true;
|
||
|
return _this.emit("end", _this.resultObject);
|
||
|
}
|
||
|
};
|
||
|
})(this);
|
||
|
ontext = (function(_this) {
|
||
|
return function(text) {
|
||
|
var charChild, s;
|
||
|
s = stack[stack.length - 1];
|
||
|
if (s) {
|
||
|
s[charkey] += text;
|
||
|
if (_this.options.explicitChildren && _this.options.preserveChildrenOrder && _this.options.charsAsChildren && (_this.options.includeWhiteChars || text.replace(/\\n/g, '').trim() !== '')) {
|
||
|
s[_this.options.childkey] = s[_this.options.childkey] || [];
|
||
|
charChild = {
|
||
|
'#name': '__text__'
|
||
|
};
|
||
|
charChild[charkey] = text;
|
||
|
if (_this.options.normalize) {
|
||
|
charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim();
|
||
|
}
|
||
|
s[_this.options.childkey].push(charChild);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
};
|
||
|
})(this);
|
||
|
this.saxParser.ontext = ontext;
|
||
|
return this.saxParser.oncdata = (function(_this) {
|
||
|
return function(text) {
|
||
|
var s;
|
||
|
s = ontext(text);
|
||
|
if (s) {
|
||
|
return s.cdata = true;
|
||
|
}
|
||
|
};
|
||
|
})(this);
|
||
|
};
|
||
|
|
||
|
Parser.prototype.parseString = function(str, cb) {
|
||
|
var err;
|
||
|
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);
|
||
|
});
|
||
|
}
|
||
|
try {
|
||
|
str = str.toString();
|
||
|
if (str.trim() === '') {
|
||
|
this.emit("end", null);
|
||
|
return true;
|
||
|
}
|
||
|
str = bom.stripBOM(str);
|
||
|
if (this.options.async) {
|
||
|
this.remaining = str;
|
||
|
setImmediate(this.processAsync);
|
||
|
return this.saxParser;
|
||
|
}
|
||
|
return this.saxParser.write(str).close();
|
||
|
} catch (error1) {
|
||
|
err = error1;
|
||
|
if (!(this.saxParser.errThrown || this.saxParser.ended)) {
|
||
|
this.emit('error', err);
|
||
|
return this.saxParser.errThrown = true;
|
||
|
} else if (this.saxParser.ended) {
|
||
|
throw err;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return Parser;
|
||
|
|
||
|
})(events.EventEmitter);
|
||
|
|
||
|
exports.parseString = function(str, a, b) {
|
||
|
var cb, options, parser;
|
||
|
if (b != null) {
|
||
|
if (typeof b === 'function') {
|
||
|
cb = b;
|
||
|
}
|
||
|
if (typeof a === 'object') {
|
||
|
options = a;
|
||
|
}
|
||
|
} else {
|
||
|
if (typeof a === 'function') {
|
||
|
cb = a;
|
||
|
}
|
||
|
options = {};
|
||
|
}
|
||
|
parser = new exports.Parser(options);
|
||
|
return parser.parseString(str, cb);
|
||
|
};
|
||
|
|
||
|
}).call(this);
|