xml2js-expat
Advanced tools
Comparing version 0.2.2 to 0.3.0
@@ -1,4 +0,4 @@ | ||
var expat = require('node-expat'), | ||
util = require('util'), | ||
events = require('events'); | ||
var expat = require('node-expat') | ||
var util = require('util') | ||
var stream = require('stream') | ||
@@ -28,18 +28,19 @@ /** | ||
var Parser = function (encoding, callback) { | ||
var that = this, | ||
stack = [], | ||
defaultEncoding = 'UTF-8'; | ||
var that = this | ||
var stack = [] | ||
var defaultEncoding = 'UTF-8' | ||
if (typeof encoding === 'function') { | ||
callback = encoding; | ||
encoding = defaultEncoding; | ||
callback = encoding | ||
encoding = defaultEncoding | ||
} | ||
// Make the sax parser. | ||
this.saxParser = new expat.Parser(encoding || defaultEncoding); | ||
this.saxParser = new expat.Parser(encoding || defaultEncoding) | ||
// Always use the '#' key, even if there are no subkeys. | ||
this.EXPLICIT_CHARKEY = false; | ||
this.resultObject = null; | ||
this.EXPLICIT_CHARKEY = false | ||
if (callback) { | ||
this.on('end', callback); | ||
this.on('end', function (result) { | ||
callback(that.getError(), result) | ||
}) | ||
this.on('error', callback) | ||
} | ||
@@ -49,34 +50,33 @@ | ||
this.saxParser.on('startElement', function (name, attributes) { | ||
var obj = {}, keys; | ||
var obj = {} | ||
obj['#'] = ""; | ||
obj['#'] = '' | ||
if (attributes) { | ||
keys = Object.keys(attributes); | ||
keys.forEach(function (k) { | ||
var v = attributes[k]; | ||
if (typeof obj['@'] === 'undefined') { | ||
obj['@'] = {}; | ||
} | ||
obj['@'][k] = v; | ||
}); | ||
var keys = Object.keys(attributes) | ||
if (keys.length) { | ||
obj['@'] = keys.reduce(function (map, key) { | ||
map[key] = attributes[key] | ||
return map | ||
}, {}) | ||
} | ||
} | ||
obj['#name'] = name; // Need a place to store the node name. | ||
stack.push(obj); | ||
}); | ||
obj['#name'] = name // Need a place to store the node name. | ||
stack.push(obj) | ||
}) | ||
// Element ended, clean up. | ||
this.saxParser.on('endElement', function (name) { | ||
var obj = stack.pop(), | ||
nodeName = obj['#name'], | ||
s = stack[stack.length - 1], | ||
old; | ||
var obj = stack.pop() | ||
var nodeName = obj['#name'] | ||
var s = stack[stack.length - 1] | ||
var old | ||
delete obj['#name']; | ||
delete obj['#name'] | ||
// Remove the '#' key altogether if it's blank. | ||
if (obj['#'].match(/^\s*$/)) { | ||
delete obj['#']; | ||
delete obj['#'] | ||
} else { | ||
// Turn 2 or more spaces into one space. | ||
obj['#'] = obj['#'].replace(/\s{2,}/g, " ").trim(); | ||
obj['#'] = obj['#'].replace(/\s{2,}/g, ' ').trim() | ||
@@ -86,3 +86,3 @@ // Also do away with '#' key altogether, if there's no subkeys | ||
if (Object.keys(obj).length === 1 && '#' in obj && !that.EXPLICIT_CHARKEY) { | ||
obj = obj['#']; | ||
obj = obj['#'] | ||
} | ||
@@ -93,63 +93,37 @@ } | ||
if (stack.length > 0) { | ||
if (typeof s[nodeName] === 'undefined') { | ||
s[nodeName] = obj; | ||
if (!(nodeName in s)) { | ||
s[nodeName] = obj | ||
} else if (s[nodeName] instanceof Array) { | ||
s[nodeName].push(obj) | ||
} else { | ||
old = s[nodeName] | ||
s[nodeName] = [old] | ||
s[nodeName].push(obj) | ||
} | ||
else if (s[nodeName] instanceof Array) { | ||
s[nodeName].push(obj); | ||
} | ||
else { | ||
old = s[nodeName]; | ||
s[nodeName] = [old]; | ||
s[nodeName].push(obj); | ||
} | ||
} else { | ||
that.resultObject = obj; | ||
that.emit("end", that.resultObject, that.getError()); | ||
that.emit('end', obj) | ||
that.emit('close') | ||
} | ||
}); | ||
}) | ||
// New text element. | ||
this.saxParser.addListener('text', function (text) { | ||
var s = stack[stack.length - 1]; | ||
this.saxParser.on('text', function (text) { | ||
var s = stack[stack.length - 1] | ||
if (s) { | ||
s['#'] += text; | ||
s['#'] += text | ||
} | ||
}); | ||
}; | ||
util.inherits(Parser, events.EventEmitter); | ||
}) | ||
/** | ||
* Parse an XML in a String or Buffer. | ||
* | ||
* @param data {String} or {Buffer} | ||
* The XML data to be parsed. | ||
* @param isFinal | ||
* Informs the parser that this is the last piece of the document. | ||
* | ||
* @returns {Boolean} | ||
* Returns false if there was a parse error. | ||
*/ | ||
Parser.prototype.parse = function (data, isFinal) { | ||
return this.saxParser.parse(data, isFinal); | ||
}; | ||
this.saxParser.on('error', this.emit.bind(this, 'error')) | ||
/** | ||
* Parse an XML string. | ||
* | ||
* @param string {String} | ||
* The XML data to be parsed. | ||
* @param isFinal | ||
* Informs the parser that this is the last piece of the document. | ||
* | ||
* @returns {Boolean} | ||
* Returns false if there was a parse error. | ||
*/ | ||
Parser.prototype.parseString = function (string, isFinal) { | ||
return this.saxParser.parse(string.toString(), isFinal); | ||
}; | ||
// Stream API | ||
this.writable = true | ||
this.readable = true | ||
} | ||
util.inherits(Parser, stream.Stream) | ||
/** | ||
* Parse an XML string. | ||
* Parse an XML in a String or Buffer. | ||
* | ||
* @param buffer {Buffer} | ||
* @param data {String|Buffer} | ||
* The XML data to be parsed. | ||
@@ -162,5 +136,4 @@ * @param isFinal | ||
*/ | ||
Parser.prototype.parseBuffer = function (buffer, isFinal) { | ||
return this.saxParser.parse(buffer, isFinal); | ||
}; | ||
Parser.prototype.parse = proxy('parse') | ||
Parser.prototype.parseString = proxy('parse') | ||
@@ -184,5 +157,3 @@ /** | ||
*/ | ||
Parser.prototype.setEncoding = function (encoding) { | ||
return this.saxParser.setEncoding(encoding); | ||
}; | ||
Parser.prototype.setEncoding = proxy('setEncoding') | ||
@@ -197,6 +168,21 @@ /** | ||
*/ | ||
Parser.prototype.getError = function () { | ||
return this.saxParser.getError(); | ||
}; | ||
Parser.prototype.getError = proxy('getError') | ||
exports.Parser = Parser; | ||
/** | ||
* Stream API | ||
*/ | ||
Parser.prototype.write = proxy('write') | ||
Parser.prototype.resume = proxy('resume') | ||
Parser.prototype.pause = proxy('pause') | ||
Parser.prototype.end = proxy('end') | ||
Parser.prototype.stop = proxy('stop') | ||
Parser.prototype.destroy = proxy('destroy') | ||
Parser.prototype.reset = proxy('reset') | ||
function proxy (method) { | ||
return function () { | ||
return this.saxParser[method].apply(this.saxParser, arguments) | ||
} | ||
} | ||
exports.Parser = Parser |
{ | ||
"name": "xml2js-expat", | ||
"version": "0.2.2", | ||
"version": "0.3.0", | ||
"description": "Simple XML to JavaScript object converter that uses Expat, a fast XML parser.", | ||
"homepage" : "https://github.com/Poetro/node-xml2js-expat", | ||
"homepage": "https://github.com/Poetro/node-xml2js-expat", | ||
"author": { | ||
"name" : "Peter Galiba (Poetro)", | ||
"email": "poetro@gmail.com>", | ||
"url" : "http://poetro.hu/" | ||
"name": "Peter Galiba (Poetro)", | ||
"email": "poetro@gmail.com", | ||
"url": "http://poetro.hu/" | ||
}, | ||
"contributors" : [ | ||
"contributors": [ | ||
{ | ||
"name" : "maqr", | ||
"name": "maqr", | ||
"email": "maqr.lollerskates@gmail.com", | ||
"url" : "https://github.com/maqr/node-xml2js/" | ||
"url": "https://github.com/maqr/node-xml2js/" | ||
} | ||
], | ||
"keywords": ["xml", "json", "expat"], | ||
"directories": { "lib": "./lib" }, | ||
"dependencies" : { "node-expat" : ">=1.0.0" }, | ||
"repository" : { | ||
"keywords": [ | ||
"xml", | ||
"json", | ||
"expat" | ||
], | ||
"directories": { | ||
"lib": "./lib" | ||
}, | ||
"dependencies": { | ||
"node-expat": ">=1.0.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url" : "https://Poetro@github.com/Poetro/node-xml2js-expat.git" | ||
"url": "https://Poetro@github.com/Poetro/node-xml2js-expat.git" | ||
}, | ||
"main" : "./lib/xml2js" | ||
"main": "./lib/xml2js", | ||
"devDependencies": { | ||
"standard": "^10.0.2", | ||
"tap": "^10.3.2" | ||
}, | ||
"scripts": { | ||
"pretest": "standard", | ||
"test": "tap test/*.test.js" | ||
} | ||
} |
@@ -6,3 +6,3 @@ node-xml2js-expat | ||
-- | ||
Simple XML to JavaScript object converter. Uses [node-expat](https://github.com/astro/node-expat). Install with [npm](http://github.com/isaacs/npm) :) | ||
Simple XML to JavaScript object converter. Uses [node-expat](https://github.com/astro/node-expat). Install with [npm](https://github.com/npm/npm) :) | ||
See the tests for examples until docs are written. | ||
@@ -14,30 +14,13 @@ Note: If you're looking for a full DOM parser, you probably want [JSDom](http://github.com/tmpvar/jsdom). | ||
var util = require('util'), | ||
fs = require('fs'), | ||
xml2js = require('xml2js-expat'); | ||
```javascript | ||
var fs = require('fs') | ||
var xml2js = require('xml2js-expat') | ||
var parser = new xml2js.Parser(function(result, error) { | ||
if (!error) { | ||
console.log(util.inspect(result)); | ||
} | ||
else { | ||
console.error(error); | ||
} | ||
console.log('Done.'); | ||
}); | ||
fs.readFile(__dirname + '/foo.xml', function(err, data) { | ||
if (parser.parseString(data)) { | ||
console.log('xml2js: successfully parsed file.'); | ||
} | ||
else { | ||
console.error('xml2js: parse error: "%s"', parser.getError()); | ||
} | ||
}); | ||
var parser = new xml2js.Parser(); | ||
fs.createReadStream('/path/to/file') | ||
.pipe(parser) | ||
.on('error', console.error.bind(console, 'xml2js: parse error:')) | ||
.on('end', console.log.bind(console, 'xml2js: successfully parsed file:')) | ||
``` | ||
The Parser object has an event, that can be suscribed to with | ||
parser.on('end', function (result, error) {}); | ||
// or | ||
parser.addListener('end', function (result, error) {}); | ||
The Parser object supports the following encodings, that can be specified as the first parameter, in which case the callback should be the second. (Each argument is optional.) | ||
@@ -52,7 +35,29 @@ | ||
var parser = new xml2js.Parser('UTF-8', function(result, error) {}); | ||
```javascript | ||
var parser = new xml2js.Parser('UTF-8', function(error, result) {}); | ||
``` | ||
or | ||
var parser = new xml2js.Parser('UTF-8'); | ||
parser.on('end', function (result, error) {}); | ||
```javascript | ||
var parser = new xml2js.Parser('UTF-8') | ||
parser.EXPLICIT_CHARKEY = true // Force text nodes to always appear as property. | ||
parser | ||
.on('end', function (result) { | ||
console.log('end', result) // end { '#': 'data' } | ||
}) | ||
.on('error', function (result) { | ||
console.log('error', result) | ||
}) | ||
.parse('<p>data</p>') | ||
``` | ||
Parser also supports streaming input: | ||
```javascript | ||
var parser = new xml2js.Parser('UTF-8'); | ||
fs.createReadStream('/path/to/file') | ||
.pipe(parser) | ||
.on('end', function(result) {}) | ||
.on('error', function(error) {}) | ||
``` |
@@ -1,59 +0,102 @@ | ||
var xml2js = require('../lib/xml2js'), | ||
fs = require('fs'), | ||
sys = require('sys'); | ||
var xml2js = require('../lib/xml2js') | ||
var fs = require('fs') | ||
var path = require('path') | ||
var tap = require('tap') | ||
module.exports = { | ||
'test default parse' : function(assert) { | ||
var x2js = new xml2js.Parser(function(r) { | ||
console.log('Result object: ' + sys.inspect(r, false, 10)); | ||
assert.equal(r['chartest']['@']['desc'], "Test for CHARs"); | ||
assert.equal(r['chartest']['#'], "Character data here!"); | ||
assert.equal(r['cdatatest']['@']['desc'], "Test for CDATA"); | ||
assert.equal(r['cdatatest']['@']['misc'], "true"); | ||
assert.equal(r['cdatatest']['#'], "CDATA here!"); | ||
assert.equal(r['nochartest']['@']['desc'], "No data"); | ||
assert.equal(r['nochartest']['@']['misc'], "false"); | ||
assert.equal(r['listtest']['item'][0]['#'], "This is character data!"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][0], "Foo(1)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][1], "Foo(2)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][2], "Foo(3)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][3], "Foo(4)"); | ||
assert.equal(r['listtest']['item'][1], "Qux."); | ||
assert.equal(r['listtest']['item'][2], "Quux."); | ||
}); | ||
tap.test('test default parse', function (assert) { | ||
var parser = new xml2js.Parser(function (error, r) { | ||
assert.same(error, null) | ||
assert.notStrictEqual(x2js, undefined); | ||
assert.equal(r['chartest']['@']['desc'], 'Test for CHARs') | ||
assert.equal(r['chartest']['#'], 'Character data here!') | ||
assert.equal(r['cdatatest']['@']['desc'], 'Test for CDATA') | ||
assert.equal(r['cdatatest']['@']['misc'], 'true') | ||
assert.equal(r['cdatatest']['#'], 'CDATA here!') | ||
assert.equal(r['nochartest']['@']['desc'], 'No data') | ||
assert.equal(r['nochartest']['@']['misc'], 'false') | ||
assert.equal(r['listtest']['item'][0]['#'], 'This is character data!') | ||
assert.equal(r['listtest']['item'][0]['subitem'][0], 'Foo(1)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][1], 'Foo(2)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][2], 'Foo(3)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][3], 'Foo(4)') | ||
assert.equal(r['listtest']['item'][1], 'Qux.') | ||
assert.equal(r['listtest']['item'][2], 'Quux.') | ||
fs.readFile(__dirname + '/fixtures/sample.xml', function(err, data) { | ||
assert.strictEqual(err, null); | ||
x2js.parse(data); | ||
}); | ||
}, | ||
'test parse EXPLICIT_CHARKEY' : function(assert) { | ||
var x2js = new xml2js.Parser(function(r) { | ||
console.log('Result object: ' + sys.inspect(r, false, 10)); | ||
assert.equal(r['chartest']['@']['desc'], "Test for CHARs"); | ||
assert.equal(r['chartest']['#'], "Character data here!"); | ||
assert.equal(r['cdatatest']['@']['desc'], "Test for CDATA"); | ||
assert.equal(r['cdatatest']['@']['misc'], "true"); | ||
assert.equal(r['cdatatest']['#'], "CDATA here!"); | ||
assert.equal(r['nochartest']['@']['desc'], "No data"); | ||
assert.equal(r['nochartest']['@']['misc'], "false"); | ||
assert.equal(r['listtest']['item'][0]['#'], "This is character data!"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][0]['#'], "Foo(1)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][1]['#'], "Foo(2)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][2]['#'], "Foo(3)"); | ||
assert.equal(r['listtest']['item'][0]['subitem'][3]['#'], "Foo(4)"); | ||
assert.equal(r['listtest']['item'][1]['#'], "Qux."); | ||
assert.equal(r['listtest']['item'][2]['#'], "Quux."); | ||
}); | ||
assert.end() | ||
}) | ||
assert.notStrictEqual(x2js, undefined); | ||
x2js.EXPLICIT_CHARKEY = true; | ||
assert.notStrictEqual(parser, undefined) | ||
fs.readFile(__dirname + '/fixtures/sample.xml', function(err, data) { | ||
assert.strictEqual(err, null); | ||
x2js.parseString(data); | ||
}); | ||
} | ||
} | ||
fs.readFile(path.join(__dirname, 'fixtures', 'sample.xml'), function (err, data) { | ||
assert.strictEqual(err, null) | ||
parser.parse(data) | ||
}) | ||
}) | ||
tap.test('test parse EXPLICIT_CHARKEY', function (assert) { | ||
var parser = new xml2js.Parser(function (error, r) { | ||
assert.same(error, null) | ||
assert.equal(r['chartest']['@']['desc'], 'Test for CHARs') | ||
assert.equal(r['chartest']['#'], 'Character data here!') | ||
assert.equal(r['cdatatest']['@']['desc'], 'Test for CDATA') | ||
assert.equal(r['cdatatest']['@']['misc'], 'true') | ||
assert.equal(r['cdatatest']['#'], 'CDATA here!') | ||
assert.equal(r['nochartest']['@']['desc'], 'No data') | ||
assert.equal(r['nochartest']['@']['misc'], 'false') | ||
assert.equal(r['listtest']['item'][0]['#'], 'This is character data!') | ||
assert.equal(r['listtest']['item'][0]['subitem'][0]['#'], 'Foo(1)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][1]['#'], 'Foo(2)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][2]['#'], 'Foo(3)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][3]['#'], 'Foo(4)') | ||
assert.equal(r['listtest']['item'][1]['#'], 'Qux.') | ||
assert.equal(r['listtest']['item'][2]['#'], 'Quux.') | ||
assert.end() | ||
}) | ||
assert.notStrictEqual(parser, undefined) | ||
parser.EXPLICIT_CHARKEY = true | ||
fs.readFile(path.join(__dirname, 'fixtures', 'sample.xml'), function (err, data) { | ||
assert.strictEqual(err, null) | ||
parser.parseString(data) | ||
}) | ||
}) | ||
tap.test('test parse stream', function (assert) { | ||
var parser = new xml2js.Parser(function (error, r) { | ||
assert.same(error, null) | ||
assert.equal(r['chartest']['@']['desc'], 'Test for CHARs') | ||
assert.equal(r['chartest']['#'], 'Character data here!') | ||
assert.equal(r['cdatatest']['@']['desc'], 'Test for CDATA') | ||
assert.equal(r['cdatatest']['@']['misc'], 'true') | ||
assert.equal(r['cdatatest']['#'], 'CDATA here!') | ||
assert.equal(r['nochartest']['@']['desc'], 'No data') | ||
assert.equal(r['nochartest']['@']['misc'], 'false') | ||
assert.equal(r['listtest']['item'][0]['#'], 'This is character data!') | ||
assert.equal(r['listtest']['item'][0]['subitem'][0], 'Foo(1)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][1], 'Foo(2)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][2], 'Foo(3)') | ||
assert.equal(r['listtest']['item'][0]['subitem'][3], 'Foo(4)') | ||
assert.equal(r['listtest']['item'][1], 'Qux.') | ||
assert.equal(r['listtest']['item'][2], 'Quux.') | ||
assert.end() | ||
}) | ||
assert.notStrictEqual(parser, undefined) | ||
fs.createReadStream(path.join(__dirname, 'fixtures', 'sample.xml')) | ||
.pipe(parser) | ||
}) | ||
tap.test('test parse error', function (assert) { | ||
var parser = new xml2js.Parser('UTF-8', function (error, r) { | ||
assert.equal(error, 'not well-formed (invalid token)') | ||
assert.end() | ||
}) | ||
assert.notStrictEqual(parser, undefined) | ||
parser.write('</end>') | ||
}) |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
12628
249
61
2
2