parser.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Generated by CoffeeScript 1.12.7
  2. (function() {
  3. "use strict";
  4. var bom, defaults, events, isEmpty, processItem, processors, sax, setImmediate,
  5. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  6. 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; },
  7. hasProp = {}.hasOwnProperty;
  8. sax = require('sax');
  9. events = require('events');
  10. bom = require('./bom');
  11. processors = require('./processors');
  12. setImmediate = require('timers').setImmediate;
  13. defaults = require('./defaults').defaults;
  14. isEmpty = function(thing) {
  15. return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
  16. };
  17. processItem = function(processors, item, key) {
  18. var i, len, process;
  19. for (i = 0, len = processors.length; i < len; i++) {
  20. process = processors[i];
  21. item = process(item, key);
  22. }
  23. return item;
  24. };
  25. exports.Parser = (function(superClass) {
  26. extend(Parser, superClass);
  27. function Parser(opts) {
  28. this.parseString = bind(this.parseString, this);
  29. this.reset = bind(this.reset, this);
  30. this.assignOrPush = bind(this.assignOrPush, this);
  31. this.processAsync = bind(this.processAsync, this);
  32. var key, ref, value;
  33. if (!(this instanceof exports.Parser)) {
  34. return new exports.Parser(opts);
  35. }
  36. this.options = {};
  37. ref = defaults["0.2"];
  38. for (key in ref) {
  39. if (!hasProp.call(ref, key)) continue;
  40. value = ref[key];
  41. this.options[key] = value;
  42. }
  43. for (key in opts) {
  44. if (!hasProp.call(opts, key)) continue;
  45. value = opts[key];
  46. this.options[key] = value;
  47. }
  48. if (this.options.xmlns) {
  49. this.options.xmlnskey = this.options.attrkey + "ns";
  50. }
  51. if (this.options.normalizeTags) {
  52. if (!this.options.tagNameProcessors) {
  53. this.options.tagNameProcessors = [];
  54. }
  55. this.options.tagNameProcessors.unshift(processors.normalize);
  56. }
  57. this.reset();
  58. }
  59. Parser.prototype.processAsync = function() {
  60. var chunk, err;
  61. try {
  62. if (this.remaining.length <= this.options.chunkSize) {
  63. chunk = this.remaining;
  64. this.remaining = '';
  65. this.saxParser = this.saxParser.write(chunk);
  66. return this.saxParser.close();
  67. } else {
  68. chunk = this.remaining.substr(0, this.options.chunkSize);
  69. this.remaining = this.remaining.substr(this.options.chunkSize, this.remaining.length);
  70. this.saxParser = this.saxParser.write(chunk);
  71. return setImmediate(this.processAsync);
  72. }
  73. } catch (error1) {
  74. err = error1;
  75. if (!this.saxParser.errThrown) {
  76. this.saxParser.errThrown = true;
  77. return this.emit(err);
  78. }
  79. }
  80. };
  81. Parser.prototype.assignOrPush = function(obj, key, newValue) {
  82. if (!(key in obj)) {
  83. if (!this.options.explicitArray) {
  84. return obj[key] = newValue;
  85. } else {
  86. return obj[key] = [newValue];
  87. }
  88. } else {
  89. if (!(obj[key] instanceof Array)) {
  90. obj[key] = [obj[key]];
  91. }
  92. return obj[key].push(newValue);
  93. }
  94. };
  95. Parser.prototype.reset = function() {
  96. var attrkey, charkey, ontext, stack;
  97. this.removeAllListeners();
  98. this.saxParser = sax.parser(this.options.strict, {
  99. trim: false,
  100. normalize: false,
  101. xmlns: this.options.xmlns
  102. });
  103. this.saxParser.errThrown = false;
  104. this.saxParser.onerror = (function(_this) {
  105. return function(error) {
  106. _this.saxParser.resume();
  107. if (!_this.saxParser.errThrown) {
  108. _this.saxParser.errThrown = true;
  109. return _this.emit("error", error);
  110. }
  111. };
  112. })(this);
  113. this.saxParser.onend = (function(_this) {
  114. return function() {
  115. if (!_this.saxParser.ended) {
  116. _this.saxParser.ended = true;
  117. return _this.emit("end", _this.resultObject);
  118. }
  119. };
  120. })(this);
  121. this.saxParser.ended = false;
  122. this.EXPLICIT_CHARKEY = this.options.explicitCharkey;
  123. this.resultObject = null;
  124. stack = [];
  125. attrkey = this.options.attrkey;
  126. charkey = this.options.charkey;
  127. this.saxParser.onopentag = (function(_this) {
  128. return function(node) {
  129. var key, newValue, obj, processedKey, ref;
  130. obj = {};
  131. obj[charkey] = "";
  132. if (!_this.options.ignoreAttrs) {
  133. ref = node.attributes;
  134. for (key in ref) {
  135. if (!hasProp.call(ref, key)) continue;
  136. if (!(attrkey in obj) && !_this.options.mergeAttrs) {
  137. obj[attrkey] = {};
  138. }
  139. newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key];
  140. processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key;
  141. if (_this.options.mergeAttrs) {
  142. _this.assignOrPush(obj, processedKey, newValue);
  143. } else {
  144. obj[attrkey][processedKey] = newValue;
  145. }
  146. }
  147. }
  148. obj["#name"] = _this.options.tagNameProcessors ? processItem(_this.options.tagNameProcessors, node.name) : node.name;
  149. if (_this.options.xmlns) {
  150. obj[_this.options.xmlnskey] = {
  151. uri: node.uri,
  152. local: node.local
  153. };
  154. }
  155. return stack.push(obj);
  156. };
  157. })(this);
  158. this.saxParser.onclosetag = (function(_this) {
  159. return function() {
  160. var cdata, emptyStr, key, node, nodeName, obj, objClone, old, s, xpath;
  161. obj = stack.pop();
  162. nodeName = obj["#name"];
  163. if (!_this.options.explicitChildren || !_this.options.preserveChildrenOrder) {
  164. delete obj["#name"];
  165. }
  166. if (obj.cdata === true) {
  167. cdata = obj.cdata;
  168. delete obj.cdata;
  169. }
  170. s = stack[stack.length - 1];
  171. if (obj[charkey].match(/^\s*$/) && !cdata) {
  172. emptyStr = obj[charkey];
  173. delete obj[charkey];
  174. } else {
  175. if (_this.options.trim) {
  176. obj[charkey] = obj[charkey].trim();
  177. }
  178. if (_this.options.normalize) {
  179. obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim();
  180. }
  181. obj[charkey] = _this.options.valueProcessors ? processItem(_this.options.valueProcessors, obj[charkey], nodeName) : obj[charkey];
  182. if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
  183. obj = obj[charkey];
  184. }
  185. }
  186. if (isEmpty(obj)) {
  187. obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr;
  188. }
  189. if (_this.options.validator != null) {
  190. xpath = "/" + ((function() {
  191. var i, len, results;
  192. results = [];
  193. for (i = 0, len = stack.length; i < len; i++) {
  194. node = stack[i];
  195. results.push(node["#name"]);
  196. }
  197. return results;
  198. })()).concat(nodeName).join("/");
  199. (function() {
  200. var err;
  201. try {
  202. return obj = _this.options.validator(xpath, s && s[nodeName], obj);
  203. } catch (error1) {
  204. err = error1;
  205. return _this.emit("error", err);
  206. }
  207. })();
  208. }
  209. if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') {
  210. if (!_this.options.preserveChildrenOrder) {
  211. node = {};
  212. if (_this.options.attrkey in obj) {
  213. node[_this.options.attrkey] = obj[_this.options.attrkey];
  214. delete obj[_this.options.attrkey];
  215. }
  216. if (!_this.options.charsAsChildren && _this.options.charkey in obj) {
  217. node[_this.options.charkey] = obj[_this.options.charkey];
  218. delete obj[_this.options.charkey];
  219. }
  220. if (Object.getOwnPropertyNames(obj).length > 0) {
  221. node[_this.options.childkey] = obj;
  222. }
  223. obj = node;
  224. } else if (s) {
  225. s[_this.options.childkey] = s[_this.options.childkey] || [];
  226. objClone = {};
  227. for (key in obj) {
  228. if (!hasProp.call(obj, key)) continue;
  229. objClone[key] = obj[key];
  230. }
  231. s[_this.options.childkey].push(objClone);
  232. delete obj["#name"];
  233. if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
  234. obj = obj[charkey];
  235. }
  236. }
  237. }
  238. if (stack.length > 0) {
  239. return _this.assignOrPush(s, nodeName, obj);
  240. } else {
  241. if (_this.options.explicitRoot) {
  242. old = obj;
  243. obj = {};
  244. obj[nodeName] = old;
  245. }
  246. _this.resultObject = obj;
  247. _this.saxParser.ended = true;
  248. return _this.emit("end", _this.resultObject);
  249. }
  250. };
  251. })(this);
  252. ontext = (function(_this) {
  253. return function(text) {
  254. var charChild, s;
  255. s = stack[stack.length - 1];
  256. if (s) {
  257. s[charkey] += text;
  258. if (_this.options.explicitChildren && _this.options.preserveChildrenOrder && _this.options.charsAsChildren && (_this.options.includeWhiteChars || text.replace(/\\n/g, '').trim() !== '')) {
  259. s[_this.options.childkey] = s[_this.options.childkey] || [];
  260. charChild = {
  261. '#name': '__text__'
  262. };
  263. charChild[charkey] = text;
  264. if (_this.options.normalize) {
  265. charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim();
  266. }
  267. s[_this.options.childkey].push(charChild);
  268. }
  269. return s;
  270. }
  271. };
  272. })(this);
  273. this.saxParser.ontext = ontext;
  274. return this.saxParser.oncdata = (function(_this) {
  275. return function(text) {
  276. var s;
  277. s = ontext(text);
  278. if (s) {
  279. return s.cdata = true;
  280. }
  281. };
  282. })(this);
  283. };
  284. Parser.prototype.parseString = function(str, cb) {
  285. var err;
  286. if ((cb != null) && typeof cb === "function") {
  287. this.on("end", function(result) {
  288. this.reset();
  289. return cb(null, result);
  290. });
  291. this.on("error", function(err) {
  292. this.reset();
  293. return cb(err);
  294. });
  295. }
  296. try {
  297. str = str.toString();
  298. if (str.trim() === '') {
  299. this.emit("end", null);
  300. return true;
  301. }
  302. str = bom.stripBOM(str);
  303. if (this.options.async) {
  304. this.remaining = str;
  305. setImmediate(this.processAsync);
  306. return this.saxParser;
  307. }
  308. return this.saxParser.write(str).close();
  309. } catch (error1) {
  310. err = error1;
  311. if (!(this.saxParser.errThrown || this.saxParser.ended)) {
  312. this.emit('error', err);
  313. return this.saxParser.errThrown = true;
  314. } else if (this.saxParser.ended) {
  315. throw err;
  316. }
  317. }
  318. };
  319. return Parser;
  320. })(events.EventEmitter);
  321. exports.parseString = function(str, a, b) {
  322. var cb, options, parser;
  323. if (b != null) {
  324. if (typeof b === 'function') {
  325. cb = b;
  326. }
  327. if (typeof a === 'object') {
  328. options = a;
  329. }
  330. } else {
  331. if (typeof a === 'function') {
  332. cb = a;
  333. }
  334. options = {};
  335. }
  336. parser = new exports.Parser(options);
  337. return parser.parseString(str, cb);
  338. };
  339. }).call(this);