add parse method to handle strings and buffers
This commit is contained in:
19
README.md
19
README.md
@@ -13,8 +13,7 @@ npm install xml-streamer
|
||||
|
||||
## Basic Usage
|
||||
|
||||
`xml-streamer can be used in three
|
||||
ways`
|
||||
`xml-streamer can be used in four ways`
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -109,6 +108,22 @@ npm install xml-streamer
|
||||
})
|
||||
}())
|
||||
|
||||
// 4. By passing a string or buffer to parse function
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var Parser = require('xml-streamer')
|
||||
|
||||
var opts = {resourcePath: '/items/item'} // resourcePath is manditory when using parse method
|
||||
|
||||
var parser = new Parser(opts)
|
||||
|
||||
parser.parse(stringOrBuffer, function (err, data) {
|
||||
// consume data here
|
||||
})
|
||||
}())
|
||||
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
121
parser.js
121
parser.js
@@ -31,13 +31,53 @@ XmlParser.prototype.checkForInterestedNodeListeners = function () {
|
||||
|
||||
XmlParser.prototype._transform = function (chunk, encoding, callback) {
|
||||
if (encoding !== 'buffer') this.emit('error', new Error('unsupported encoding'))
|
||||
if (this.parserState.isRootNode) this.checkForInterestedNodeListeners()
|
||||
|
||||
this.parse(chunk)
|
||||
this.processChunk(chunk)
|
||||
callback()
|
||||
}
|
||||
|
||||
XmlParser.prototype.parse = function (chunk) {
|
||||
XmlParser.prototype.processChunk = function (chunk) {
|
||||
var parser = this.parser
|
||||
var state = this.parserState
|
||||
|
||||
if (state.isRootNode) {
|
||||
this.checkForInterestedNodeListeners()
|
||||
registerEvents.call(this)
|
||||
}
|
||||
|
||||
if (typeof chunk === 'string') {
|
||||
if (!parser.parse('', true)) processError.call(this)
|
||||
} else {
|
||||
if (!parser.parse(chunk.toString())) processError.call(this)
|
||||
}
|
||||
}
|
||||
|
||||
XmlParser.prototype.parse = function (chunk, cb) {
|
||||
var parser = this.parser
|
||||
var state = this.parserState
|
||||
var error
|
||||
|
||||
if (state.isRootNode) {
|
||||
this.checkForInterestedNodeListeners()
|
||||
registerEvents.call(this)
|
||||
}
|
||||
|
||||
if (typeof chunk === Buffer) chunk = chunk.toString()
|
||||
|
||||
this.on('error', function (err) {
|
||||
error = err
|
||||
})
|
||||
|
||||
if (!parser.parse(chunk)) {
|
||||
error = processError.call(this)
|
||||
}
|
||||
|
||||
if (error) return cb(error)
|
||||
|
||||
return cb(null, this._readableState.buffer)
|
||||
}
|
||||
|
||||
function registerEvents () {
|
||||
var scope = this
|
||||
var parser = this.parser
|
||||
var state = this.parserState
|
||||
@@ -47,49 +87,28 @@ XmlParser.prototype.parse = function (chunk) {
|
||||
var textKey = this.opts.textKey
|
||||
var interestedNodes = state.interestedNodes
|
||||
|
||||
if (state.isRootNode) registerEvents()
|
||||
parser.on('startElement', function (name, attrs) {
|
||||
if (state.isRootNode) validateResourcePath(name)
|
||||
state.currentPath = state.currentPath + '/' + name
|
||||
checkForResourcePath(name)
|
||||
if (state.isPathfound) processStartElement(name, attrs)
|
||||
})
|
||||
|
||||
if (typeof chunk === 'string') {
|
||||
if (!parser.parse('', true)) processError()
|
||||
} else {
|
||||
if (!parser.parse(chunk.toString())) processError()
|
||||
}
|
||||
parser.on('endElement', function (name) {
|
||||
state.lastEndedNode = name
|
||||
lastIndex = state.currentPath.lastIndexOf('/' + name)
|
||||
state.currentPath = state.currentPath.substring(0, lastIndex)
|
||||
if (state.isPathfound) processEndElement(name)
|
||||
checkForResourcePath(name)
|
||||
})
|
||||
|
||||
function registerEvents () {
|
||||
parser.on('startElement', function (name, attrs) {
|
||||
if (state.isRootNode) validateResourcePath(name)
|
||||
state.currentPath = state.currentPath + '/' + name
|
||||
checkForResourcePath(name)
|
||||
if (state.isPathfound) processStartElement(name, attrs)
|
||||
})
|
||||
parser.on('text', function (text) {
|
||||
if (state.isPathfound) processText(text)
|
||||
})
|
||||
|
||||
parser.on('endElement', function (name) {
|
||||
state.lastEndedNode = name
|
||||
lastIndex = state.currentPath.lastIndexOf('/' + name)
|
||||
state.currentPath = state.currentPath.substring(0, lastIndex)
|
||||
if (state.isPathfound) processEndElement(name)
|
||||
checkForResourcePath(name)
|
||||
})
|
||||
|
||||
parser.on('text', function (text) {
|
||||
if (state.isPathfound) processText(text)
|
||||
})
|
||||
|
||||
parser.on('error', function (err) {
|
||||
processError(err)
|
||||
})
|
||||
}
|
||||
|
||||
function processError (err) {
|
||||
var error = ''
|
||||
|
||||
if (err) {
|
||||
error = err
|
||||
} else {
|
||||
error = parser.getError()
|
||||
}
|
||||
scope.emit('error', new Error(error + ' at line no: ' + parser.getCurrentLineNumber()))
|
||||
}
|
||||
parser.on('error', function (err) {
|
||||
processError.call(this, err)
|
||||
})
|
||||
|
||||
function processStartElement (name, attrs) {
|
||||
if (!name) return
|
||||
@@ -243,8 +262,22 @@ XmlParser.prototype.parse = function (chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
function processError (err) {
|
||||
var parser = this.parser
|
||||
var error = ''
|
||||
|
||||
if (err) {
|
||||
error = err
|
||||
} else {
|
||||
error = parser.getError()
|
||||
}
|
||||
error = new Error(error + ' at line no: ' + parser.getCurrentLineNumber())
|
||||
this.emit('error', error)
|
||||
return error
|
||||
}
|
||||
|
||||
XmlParser.prototype._flush = function (callback) {
|
||||
this.parse('', true)
|
||||
this.processChunk('')
|
||||
callback()
|
||||
}
|
||||
|
||||
|
||||
83
test/test.js
83
test/test.js
@@ -1227,4 +1227,87 @@ describe('Tests', function () {
|
||||
xmlStream.pipe(parser)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Parse funtion should work properly', function () {
|
||||
it('should properly parse a simple file.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/item.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
var expectedData = [
|
||||
{ '$': { id: '1', test: 'hello' },
|
||||
subitem:
|
||||
[ { '$': { sub: 'TESTING SUB' }, _: 'one' },
|
||||
{ '$': { sub: '2' }, _: 'two' } ] },
|
||||
{ '$': { id: '2' },
|
||||
subitem: [ { _: 'three' }, { _: 'four' }, { _: 'five' } ] } ]
|
||||
|
||||
parser.parse(xml.toString(), function (err, data) {
|
||||
if (err) done(err)
|
||||
data.should.deepEqual(expectedData)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should properly parse a medium size file.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/medium.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
|
||||
parser.parse(xml, function (err, data) {
|
||||
if (err) done(err)
|
||||
data.length.should.equal(10)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should properly parse a file containing many nodes.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/manyItems.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
|
||||
parser.parse(xml, function (err, data) {
|
||||
if (err) done(err)
|
||||
data.length.should.equal(296)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should properly parse a xml simple file in which nodes contain text values randomly.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/randomText.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
var expectedData = [ { '$': { 'id': '1', 'test': 'hello' }, '_': ' item one two',
|
||||
'subitem': [ { '$': { 'sub': 'TESTING SUB' }, '_': 'one' },
|
||||
{ '$': { 'sub': '2' }, '_': 'two' } ] },
|
||||
{ '$': { 'id': '2' }, '_': ' item one two three four',
|
||||
'subitem': [ { '_': 'three' }, { '_': 'four' }, { '_': 'five' } ] }
|
||||
]
|
||||
|
||||
parser.parse(xml, function (err, data) {
|
||||
if (err) done(err)
|
||||
data.should.deepEqual(expectedData)
|
||||
data.length.should.equal(2)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should properly parse a huge file.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/hugeFile.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
// console.log(parser)
|
||||
parser.parse(xml, function (err, data) {
|
||||
if (err) done(err)
|
||||
data.length.should.equal(2072)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should properly return error if the xml file is corrupted.', function (done) {
|
||||
var xml = fs.readFileSync('./test/TestFiles/corrupted.xml')
|
||||
var parser = new ParserFactory({resourcePath: '/items/item'})
|
||||
|
||||
parser.parse(xml, function (err, data) {
|
||||
// console.log(err)
|
||||
err.message.should.equal('mismatched tag at line no: 11')
|
||||
should(data).not.be.ok()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user