437 lines
13 KiB
JavaScript
437 lines
13 KiB
JavaScript
|
// Generated by CoffeeScript 1.7.1
|
||
|
(function() {
|
||
|
var bom, builder, events, isEmpty, processName, processors, 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');
|
||
|
|
||
|
builder = require('xmlbuilder');
|
||
|
|
||
|
bom = require('./bom');
|
||
|
|
||
|
processors = require('./processors');
|
||
|
|
||
|
isEmpty = function(thing) {
|
||
|
return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
|
||
|
};
|
||
|
|
||
|
processName = function(processors, processedName) {
|
||
|
var process, _i, _len;
|
||
|
for (_i = 0, _len = processors.length; _i < _len; _i++) {
|
||
|
process = processors[_i];
|
||
|
processedName = process(processedName);
|
||
|
}
|
||
|
return processedName;
|
||
|
};
|
||
|
|
||
|
exports.processors = processors;
|
||
|
|
||
|
exports.defaults = {
|
||
|
"0.1": {
|
||
|
explicitCharkey: false,
|
||
|
trim: true,
|
||
|
normalize: true,
|
||
|
normalizeTags: false,
|
||
|
attrkey: "@",
|
||
|
charkey: "#",
|
||
|
explicitArray: false,
|
||
|
ignoreAttrs: false,
|
||
|
mergeAttrs: false,
|
||
|
explicitRoot: false,
|
||
|
validator: null,
|
||
|
xmlns: false,
|
||
|
explicitChildren: false,
|
||
|
childkey: '@@',
|
||
|
charsAsChildren: false,
|
||
|
async: false,
|
||
|
strict: true,
|
||
|
attrNameProcessors: null,
|
||
|
tagNameProcessors: null
|
||
|
},
|
||
|
"0.2": {
|
||
|
explicitCharkey: false,
|
||
|
trim: false,
|
||
|
normalize: false,
|
||
|
normalizeTags: false,
|
||
|
attrkey: "$",
|
||
|
charkey: "_",
|
||
|
explicitArray: true,
|
||
|
ignoreAttrs: false,
|
||
|
mergeAttrs: false,
|
||
|
explicitRoot: true,
|
||
|
validator: null,
|
||
|
xmlns: false,
|
||
|
explicitChildren: false,
|
||
|
childkey: '$$',
|
||
|
charsAsChildren: false,
|
||
|
async: false,
|
||
|
strict: true,
|
||
|
attrNameProcessors: null,
|
||
|
tagNameProcessors: null,
|
||
|
rootName: 'root',
|
||
|
xmldec: {
|
||
|
'version': '1.0',
|
||
|
'encoding': 'UTF-8',
|
||
|
'standalone': true
|
||
|
},
|
||
|
doctype: null,
|
||
|
renderOpts: {
|
||
|
'pretty': true,
|
||
|
'indent': ' ',
|
||
|
'newline': '\n'
|
||
|
},
|
||
|
headless: false
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.ValidationError = (function(_super) {
|
||
|
__extends(ValidationError, _super);
|
||
|
|
||
|
function ValidationError(message) {
|
||
|
this.message = message;
|
||
|
}
|
||
|
|
||
|
return ValidationError;
|
||
|
|
||
|
})(Error);
|
||
|
|
||
|
exports.Builder = (function() {
|
||
|
function Builder(opts) {
|
||
|
var key, value, _ref;
|
||
|
this.options = {};
|
||
|
_ref = exports.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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Builder.prototype.buildObject = function(rootObj) {
|
||
|
var attrkey, charkey, render, rootElement, rootName;
|
||
|
attrkey = this.options.attrkey;
|
||
|
charkey = this.options.charkey;
|
||
|
if ((Object.keys(rootObj).length === 1) && (this.options.rootName === exports.defaults['0.2'].rootName)) {
|
||
|
rootName = Object.keys(rootObj)[0];
|
||
|
rootObj = rootObj[rootName];
|
||
|
} else {
|
||
|
rootName = this.options.rootName;
|
||
|
}
|
||
|
render = function(element, obj) {
|
||
|
var attr, child, entry, index, key, value, _ref, _ref1;
|
||
|
if (typeof obj !== 'object') {
|
||
|
element.txt(obj);
|
||
|
} else {
|
||
|
for (key in obj) {
|
||
|
if (!__hasProp.call(obj, key)) continue;
|
||
|
child = obj[key];
|
||
|
if (key === attrkey) {
|
||
|
if (typeof child === "object") {
|
||
|
for (attr in child) {
|
||
|
value = child[attr];
|
||
|
element = element.att(attr, value);
|
||
|
}
|
||
|
}
|
||
|
} else if (key === charkey) {
|
||
|
element = element.txt(child);
|
||
|
} else if (typeof child === 'object' && ((child != null ? child.constructor : void 0) != null) && ((child != null ? (_ref = child.constructor) != null ? _ref.name : void 0 : void 0) != null) && (child != null ? (_ref1 = child.constructor) != null ? _ref1.name : void 0 : void 0) === 'Array') {
|
||
|
for (index in child) {
|
||
|
if (!__hasProp.call(child, index)) continue;
|
||
|
entry = child[index];
|
||
|
if (typeof entry === 'string') {
|
||
|
element = element.ele(key, entry).up();
|
||
|
} else {
|
||
|
element = arguments.callee(element.ele(key), entry).up();
|
||
|
}
|
||
|
}
|
||
|
} else if (typeof child === "object") {
|
||
|
element = arguments.callee(element.ele(key), child).up();
|
||
|
} else {
|
||
|
element = element.ele(key, child.toString()).up();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return element;
|
||
|
};
|
||
|
rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, {
|
||
|
headless: this.options.headless
|
||
|
});
|
||
|
return render(rootElement, rootObj).end(this.options.renderOpts);
|
||
|
};
|
||
|
|
||
|
return Builder;
|
||
|
|
||
|
})();
|
||
|
|
||
|
exports.Parser = (function(_super) {
|
||
|
__extends(Parser, _super);
|
||
|
|
||
|
function Parser(opts) {
|
||
|
this.parseString = __bind(this.parseString, this);
|
||
|
this.reset = __bind(this.reset, this);
|
||
|
this.assignOrPush = __bind(this.assignOrPush, this);
|
||
|
var key, value, _ref;
|
||
|
if (!(this instanceof exports.Parser)) {
|
||
|
return new exports.Parser(opts);
|
||
|
}
|
||
|
this.options = {};
|
||
|
_ref = exports.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.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.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 = node.attributes[key];
|
||
|
processedKey = _this.options.attrNameProcessors ? processName(_this.options.attrNameProcessors, key) : key;
|
||
|
if (_this.options.mergeAttrs) {
|
||
|
_this.assignOrPush(obj, processedKey, newValue);
|
||
|
} else {
|
||
|
obj[attrkey][processedKey] = newValue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
obj["#name"] = _this.options.tagNameProcessors ? processName(_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, err, node, nodeName, obj, old, s, xpath;
|
||
|
obj = stack.pop();
|
||
|
nodeName = obj["#name"];
|
||
|
delete obj["#name"];
|
||
|
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();
|
||
|
}
|
||
|
if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
|
||
|
obj = obj[charkey];
|
||
|
}
|
||
|
}
|
||
|
if (isEmpty(obj)) {
|
||
|
obj = _this.options.emptyTag !== void 0 ? _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("/");
|
||
|
try {
|
||
|
obj = _this.options.validator(xpath, s && s[nodeName], obj);
|
||
|
} catch (_error) {
|
||
|
err = _error;
|
||
|
_this.emit("error", err);
|
||
|
}
|
||
|
}
|
||
|
if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') {
|
||
|
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;
|
||
|
}
|
||
|
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 s;
|
||
|
s = stack[stack.length - 1];
|
||
|
if (s) {
|
||
|
s[charkey] += text;
|
||
|
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();
|
||
|
if (this.options.async) {
|
||
|
return process.nextTick(function() {
|
||
|
return cb(null, result);
|
||
|
});
|
||
|
} else {
|
||
|
return cb(null, result);
|
||
|
}
|
||
|
});
|
||
|
this.on("error", function(err) {
|
||
|
this.reset();
|
||
|
if (this.options.async) {
|
||
|
return process.nextTick(function() {
|
||
|
return cb(err);
|
||
|
});
|
||
|
} else {
|
||
|
return cb(err);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
if (str.toString().trim() === '') {
|
||
|
this.emit("end", null);
|
||
|
return true;
|
||
|
}
|
||
|
try {
|
||
|
return this.saxParser.write(bom.stripBOM(str.toString())).close();
|
||
|
} catch (_error) {
|
||
|
err = _error;
|
||
|
if (!(this.saxParser.errThrown || this.saxParser.ended)) {
|
||
|
this.emit('error', err);
|
||
|
return this.saxParser.errThrown = true;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
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);
|