123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- //////////////////////////////////////////
- // Defines mappings between content-type
- // and the appropriate parsers.
- //////////////////////////////////////////
-
- var Transform = require('stream').Transform;
- var sax = require('sax');
-
- function parseXML(str, cb) {
- var obj, current, parser = sax.parser(true, { trim: true, lowercase: true })
- parser.onerror = parser.onend = done;
-
- function done(err) {
- parser.onerror = parser.onend = function() { }
- cb(err, obj)
- }
-
- function newElement(name, attributes) {
- return {
- name: name || '',
- value: '',
- attributes: attributes || {},
- children: []
- }
- }
-
- parser.oncdata = parser.ontext = function(t) {
- if (current) current.value += t
- }
-
- parser.onopentag = function(node) {
- var element = newElement(node.name, node.attributes)
- if (current) {
- element.parent = current
- current.children.push(element)
- } else { // root object
- obj = element
- }
-
- current = element
- };
-
- parser.onclosetag = function() {
- if (typeof current.parent !== 'undefined') {
- var just_closed = current
- current = current.parent
- delete just_closed.parent
- }
- }
-
- parser.write(str).close()
- }
-
- function parserFactory(name, fn) {
-
- function parser() {
- var chunks = [],
- stream = new Transform({ objectMode: true });
-
- // Buffer all our data
- stream._transform = function(chunk, encoding, done) {
- chunks.push(chunk);
- done();
- }
-
- // And call the parser when all is there.
- stream._flush = function(done) {
- var self = this,
- data = Buffer.concat(chunks);
-
- try {
- fn(data, function(err, result) {
- if (err) throw err;
- self.push(result);
- });
- } catch (err) {
- self.push(data); // just pass the original data
- } finally {
- done();
- }
- }
-
- return stream;
- }
-
- return { fn: parser, name: name };
- }
-
- var parsers = {}
-
- function buildParser(name, types, fn) {
- var parser = parserFactory(name, fn);
- types.forEach(function(type) {
- parsers[type] = parser;
- })
- }
-
- buildParser('json', [
- 'application/json',
- 'text/javascript',
- 'application/vnd.api+json'
- ], function(buffer, cb) {
- var err, data;
- try { data = JSON.parse(buffer); } catch (e) { err = e; }
- cb(err, data);
- });
-
- buildParser('xml', [
- 'text/xml',
- 'application/xml',
- 'application/rdf+xml',
- 'application/rss+xml',
- 'application/atom+xml'
- ], function(buffer, cb) {
- parseXML(buffer.toString(), function(err, obj) {
- cb(err, obj)
- })
- });
-
- module.exports = parsers;
- module.exports.use = buildParser;
|