diff --git a/src/ltx.ts b/src/ltx.ts index e725ee3..6bad2ae 100644 --- a/src/ltx.ts +++ b/src/ltx.ts @@ -1,229 +1,228 @@ // Source: https://github.com/xmppjs/ltx/blob/master/lib/parsers/ltx.js -import events from "events"; -import { unescapeXML } from "./unescape"; +import events from 'events' +import { unescapeXML } from './unescape' -const STATE_TEXT = 0; -const STATE_IGNORE_COMMENT = 1; -const STATE_IGNORE_INSTRUCTION = 2; -const STATE_TAG_NAME = 3; -const STATE_TAG = 4; -const STATE_ATTR_NAME = 5; -const STATE_ATTR_EQ = 6; -const STATE_ATTR_QUOT = 7; -const STATE_ATTR_VALUE = 8; -const STATE_CDATA = 9; +const STATE_TEXT = 0 +const STATE_IGNORE_COMMENT = 1 +const STATE_IGNORE_INSTRUCTION = 2 +const STATE_TAG_NAME = 3 +const STATE_TAG = 4 +const STATE_ATTR_NAME = 5 +const STATE_ATTR_EQ = 6 +const STATE_ATTR_QUOT = 7 +const STATE_ATTR_VALUE = 8 +const STATE_CDATA = 9 -const lineCounterRegExp = new RegExp("\n", "g"); +const lineCounterRegExp = new RegExp('\n', 'g') export class SaxLtx extends events.EventEmitter { - public remainder: string; - public tagName: string; - public attrs: any; - public endTag: boolean; - public selfClosing: boolean; - public attrQuote: number; - public attrQuoteChar: string; - public recordStart = 0; - public attrName: string; - public state = STATE_TEXT; + public remainder: string + public tagName: string + public attrs: any + public endTag: boolean + public selfClosing: boolean + public attrQuote: number + public attrQuoteChar: string + public recordStart = 0 + public attrName: string + public state = STATE_TEXT - public currentLineNumber = 0; + public currentLineNumber = 0 constructor() { - super(); - + super() } public getCurrentLineNumber() { - return this.currentLineNumber + 1; + return this.currentLineNumber + 1 } public end(data?: Buffer) { if (data) { - this.write(data); + this.write(data) } - this.removeAllListeners(); + this.removeAllListeners() } public write(data: Buffer | string) { - if (typeof data !== "string") { - data = data.toString(); + if (typeof data !== 'string') { + data = data.toString() } - let pos = 0; - const self = this; + let pos = 0 + const self = this /* Anything from previous write()? */ if (self.remainder) { - data = self.remainder + data; - pos += self.remainder.length; - self.remainder = null; + data = self.remainder + data + pos += self.remainder.length + self.remainder = null } function endRecording() { - if (typeof self.recordStart === "number") { - const recorded = (data as string).substring(self.recordStart, pos); - self.recordStart = undefined; - return recorded; + if (typeof self.recordStart === 'number') { + const recorded = (data as string).substring(self.recordStart, pos) + self.recordStart = undefined + return recorded } } - let prevPos = pos; + let prevPos = pos for (; pos < data.length; pos++) { - if (self.state === STATE_TEXT) { // if we're looping through text, fast-forward using indexOf to // the next '<' character - const lt = data.indexOf("<", pos); + const lt = data.indexOf('<', pos) if (lt !== -1 && pos !== lt) { - pos = lt; + pos = lt } } else if (self.state === STATE_ATTR_VALUE) { // if we're looping through an attribute, fast-forward using // indexOf to the next end quote character - const quot = data.indexOf(self.attrQuoteChar, pos); + const quot = data.indexOf(self.attrQuoteChar, pos) if (quot !== -1) { - pos = quot; + pos = quot } } else if (self.state === STATE_IGNORE_COMMENT) { // if we're looping through a comment, fast-forward using // indexOf to the first end-comment character - const endcomment = data.indexOf("-->", pos); + const endcomment = data.indexOf('-->', pos) if (endcomment !== -1) { - pos = endcomment + 2; // target the '>' character + pos = endcomment + 2 // target the '>' character } } - const newLines = (data.substring(prevPos, pos + 1).match(lineCounterRegExp) || []).length; - self.currentLineNumber += newLines; - prevPos = pos; + const newLines = (data.substring(prevPos, pos + 1).match(lineCounterRegExp) || []).length + self.currentLineNumber += newLines + prevPos = pos - const c = data.charCodeAt(pos); + const c = data.charCodeAt(pos) switch (self.state) { case STATE_TEXT: if (c === 60 /* < */) { - const text = endRecording(); + const text = endRecording() if (text) { - self.emit("text", unescapeXML(text)); + self.emit('text', unescapeXML(text)) } - self.state = STATE_TAG_NAME; - self.recordStart = pos + 1; - self.attrs = {}; + self.state = STATE_TAG_NAME + self.recordStart = pos + 1 + self.attrs = {} } - break; + break case STATE_CDATA: - if (c === 93 /* ] */ && data.substr(pos + 1, 2) === "]>") { - const cData = endRecording(); + if (c === 93 /* ] */ && data.substr(pos + 1, 2) === ']>') { + const cData = endRecording() if (cData) { - self.emit("text", cData); + self.emit('text', cData) } - self.state = STATE_IGNORE_COMMENT; + self.state = STATE_IGNORE_COMMENT } - break; + break case STATE_TAG_NAME: if (c === 47 /* / */ && self.recordStart === pos) { - self.recordStart = pos + 1; - self.endTag = true; + self.recordStart = pos + 1 + self.endTag = true } else if (c === 33 /* ! */) { - if (data.substr(pos + 1, 7) === "[CDATA[") { - self.recordStart = pos + 8; - self.state = STATE_CDATA; - } else if (data.substr(pos + 1, 7) === "DOCTYPE") { - self.recordStart = pos + 8; - self.state = STATE_TEXT; + if (data.substr(pos + 1, 7) === '[CDATA[') { + self.recordStart = pos + 8 + self.state = STATE_CDATA + } else if (data.substr(pos + 1, 7) === 'DOCTYPE') { + self.recordStart = pos + 8 + self.state = STATE_TEXT } else { - self.recordStart = undefined; - self.state = STATE_IGNORE_COMMENT; + self.recordStart = undefined + self.state = STATE_IGNORE_COMMENT } } else if (c === 63 /* ? */) { - self.recordStart = undefined; - self.state = STATE_IGNORE_INSTRUCTION; + self.recordStart = undefined + self.state = STATE_IGNORE_INSTRUCTION } else if (c <= 32 || c === 47 /* / */ || c === 62 /* > */) { - self.tagName = endRecording(); - pos--; - self.state = STATE_TAG; + self.tagName = endRecording() + pos-- + self.state = STATE_TAG } - break; + break case STATE_IGNORE_COMMENT: if (c === 62 /* > */) { - const prevFirst = data.charCodeAt(pos - 1); - const prevSecond = data.charCodeAt(pos - 2); - if ((prevFirst === 45 /* - */ && prevSecond === 45 /* - */) || - (prevFirst === 93 /* ] */ && prevSecond === 93 /* ] */)) { - self.state = STATE_TEXT; + const prevFirst = data.charCodeAt(pos - 1) + const prevSecond = data.charCodeAt(pos - 2) + if ( + (prevFirst === 45 /* - */ && prevSecond === 45) /* - */ || + (prevFirst === 93 /* ] */ && prevSecond === 93) /* ] */ + ) { + self.state = STATE_TEXT } } - break; + break case STATE_IGNORE_INSTRUCTION: if (c === 62 /* > */) { - const prev = data.charCodeAt(pos - 1); + const prev = data.charCodeAt(pos - 1) if (prev === 63 /* ? */) { - self.state = STATE_TEXT; + self.state = STATE_TEXT } } - break; + break case STATE_TAG: if (c === 62 /* > */) { - self._handleTagOpening(self.endTag, self.tagName, self.attrs); - self.tagName = undefined; - self.attrs = undefined; - self.endTag = undefined; - self.selfClosing = undefined; - self.state = STATE_TEXT; - self.recordStart = pos + 1; + self._handleTagOpening(self.endTag, self.tagName, self.attrs) + self.tagName = undefined + self.attrs = undefined + self.endTag = undefined + self.selfClosing = undefined + self.state = STATE_TEXT + self.recordStart = pos + 1 } else if (c === 47 /* / */) { - self.selfClosing = true; + self.selfClosing = true } else if (c > 32) { - self.recordStart = pos; - self.state = STATE_ATTR_NAME; + self.recordStart = pos + self.state = STATE_ATTR_NAME } - break; + break case STATE_ATTR_NAME: if (c <= 32 || c === 61 /* = */) { - self.attrName = endRecording(); - pos--; - self.state = STATE_ATTR_EQ; + self.attrName = endRecording() + pos-- + self.state = STATE_ATTR_EQ } - break; + break case STATE_ATTR_EQ: if (c === 61 /* = */) { - self.state = STATE_ATTR_QUOT; + self.state = STATE_ATTR_QUOT } - break; + break case STATE_ATTR_QUOT: if (c === 34 /* " */ || c === 39 /* ' */) { - self.attrQuote = c; - self.attrQuoteChar = c === 34 ? '"' : "'"; - self.state = STATE_ATTR_VALUE; - self.recordStart = pos + 1; + self.attrQuote = c + self.attrQuoteChar = c === 34 ? '"' : "'" + self.state = STATE_ATTR_VALUE + self.recordStart = pos + 1 } - break; + break case STATE_ATTR_VALUE: if (c === self.attrQuote) { - const value = unescapeXML(endRecording()); - self.attrs[self.attrName] = value; - self.attrName = undefined; - self.state = STATE_TAG; + const value = unescapeXML(endRecording()) + self.attrs[self.attrName] = value + self.attrName = undefined + self.state = STATE_TAG } - break; + break } } - if (typeof self.recordStart === "number" && - self.recordStart <= data.length) { - self.remainder = data.slice(self.recordStart); - self.recordStart = 0; + if (typeof self.recordStart === 'number' && self.recordStart <= data.length) { + self.remainder = data.slice(self.recordStart) + self.recordStart = 0 } } private _handleTagOpening(endTag: boolean, tagName: string, attrs: string) { if (!endTag) { - this.emit("startElement", tagName, attrs); + this.emit('startElement', tagName, attrs) if (this.selfClosing) { - this.emit("endElement", tagName); + this.emit('endElement', tagName) } } else { - this.emit("endElement", tagName); + this.emit('endElement', tagName) } } } diff --git a/src/parser.ts b/src/parser.ts index c8d1dbe..59162a3 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,56 +1,55 @@ -import _ from "lodash"; -import stream from "stream"; -import util from "util"; +import _ from 'lodash' +import stream from 'stream' +import util from 'util' -import { SaxLtx } from "./ltx"; -import { ParserState } from "./parserState"; +import { SaxLtx } from './ltx' +import { ParserState } from './parserState' const defaults = { - resourcePath: "", + resourcePath: '', emitOnNodeName: false, - attrsKey: "$", - textKey: "_", + attrsKey: '$', + textKey: '_', explicitArray: true, verbatimText: false, preserveWhitespace: false -}; +} export interface IXmlParserOptions { - /** * Optional field. Used to extract the XML nodes that you are interested in. * * @type {string} * @memberof IXmlParserOptions */ - resourcePath?: string; + resourcePath?: string /** * Optional field. Set this to true if you want to listen on node names instead of data event. default: false * * @type {boolean} * @memberof IXmlParserOptions */ - emitOnNodeName?: boolean; + emitOnNodeName?: boolean /** * Optional field. pass the value with which you want to reference attributes of a node in its object form. default: '$' * * @type {string} * @memberof IXmlParserOptions */ - attrsKey?: string; + attrsKey?: string /** * Optional field. pass the value with which you want to reference node value in its object form. default: '_' * * @type {string} * @memberof IXmlParserOptions */ - textKey?: string; + textKey?: string /** * Optional field. Default value is true. All children nodes will come in an array when this option is true. * * @type {boolean} * @memberof IXmlParserOptions */ - explicitArray?: boolean; + explicitArray?: boolean /** * Optional field. Default value is false. When set, text attribute will include all blanks found in xml. * When unset, blanks are removed as long as they come in one expat single block (blank lines, newlines and entities). @@ -58,299 +57,334 @@ export interface IXmlParserOptions { * @type {boolean} * @memberof IXmlParserOptions */ - verbatimText?: boolean; - preserveWhitespace?: boolean; + verbatimText?: boolean + preserveWhitespace?: boolean } export class XmlParser extends stream.Transform { - public parserState: ParserState; - private opts: IXmlParserOptions; - private _readableState: { objectMode: true, buffer: any }; - private parser: SaxLtx; + public parserState: ParserState + private opts: IXmlParserOptions + private _readableState: { objectMode: true; buffer: any } + private parser: SaxLtx constructor(opts?: IXmlParserOptions) { - super(); - this.opts = _.defaults(opts, defaults); - this.parserState = new ParserState(); - this.parser = new SaxLtx(); - this._readableState.objectMode = true; + super() + this.opts = _.defaults(opts, defaults) + this.parserState = new ParserState() + this.parser = new SaxLtx() + this._readableState.objectMode = true } public _flush(callback: () => void) { - this.processChunk(""); - callback(); + this.processChunk('') + callback() } public _transform(chunk: Buffer | string, encoding: string, callback: () => void) { - if (encoding !== "buffer") { this.emit("error", new Error("unsupported encoding")); } + if (encoding !== 'buffer') { + this.emit('error', new Error('unsupported encoding')) + } - this.processChunk(chunk); - callback(); + this.processChunk(chunk) + callback() } public parse(chunk: Buffer | string, cb: (error: Error, data?: Buffer) => void) { - const parser = this.parser; - const state = this.parserState; - let error; + const parser = this.parser + const state = this.parserState + let error if (state.isRootNode) { - this.checkForInterestedNodeListeners(); - registerEvents.call(this); + this.checkForInterestedNodeListeners() + registerEvents.call(this) } - this.on("error", (err) => { - error = err; - }); + this.on('error', (err) => { + error = err + }) if (chunk.length === 0) { - parser.end(); - this.emit("end"); - this.removeAllListeners(); + parser.end() + this.emit('end') + this.removeAllListeners() } - parser.write(chunk); + parser.write(chunk) - if (error) { return cb(error); } + if (error) { + return cb(error) + } - const result = []; + const result = [] while (this._readableState.buffer.length > 0) { - result.push(this._readableState.buffer.consume()); + result.push(this._readableState.buffer.consume()) } - return cb(null, result as any); + return cb(null, result as any) } private processChunk(chunk: string | Buffer) { - const parser = this.parser; - const state = this.parserState; + const parser = this.parser + const state = this.parserState if (state.isRootNode) { - this.checkForInterestedNodeListeners(); - registerEvents.call(this); + this.checkForInterestedNodeListeners() + registerEvents.call(this) } - parser.write(chunk); + parser.write(chunk) } private checkForInterestedNodeListeners() { - const ignore = ["end", "prefinish", "data", "error"]; - const eventNames = Object.keys((this as any)._events); + const ignore = ['end', 'prefinish', 'data', 'error'] + const eventNames = Object.keys((this as any)._events) // tslint:disable-next-line:prefer-for-of for (let i = 0; i < eventNames.length; i++) { - if (_.includes(ignore, eventNames[i], 0)) { continue; } - this.parserState.interestedNodes.push(eventNames[i]); + if (_.includes(ignore, eventNames[i], 0)) { + continue + } + this.parserState.interestedNodes.push(eventNames[i]) } } - } function registerEvents() { - const scope = this; - const parser: SaxLtx = this.parser; - const state: ParserState = this.parserState; - let lastIndex; - const resourcePath = this.opts.resourcePath; - const attrsKey = this.opts.attrsKey; - const textKey = this.opts.textKey; - const interestedNodes = state.interestedNodes; - const explicitArray = this.opts.explicitArray; - const verbatimText = this.opts.verbatimText; - const preserveWhitespace = this.opts.preserveWhitespace; + const scope = this + const parser: SaxLtx = this.parser + const state: ParserState = this.parserState + let lastIndex + const resourcePath = this.opts.resourcePath + const attrsKey = this.opts.attrsKey + const textKey = this.opts.textKey + const interestedNodes = state.interestedNodes + const explicitArray = this.opts.explicitArray + const verbatimText = this.opts.verbatimText + const preserveWhitespace = this.opts.preserveWhitespace - parser.on("startElement", (name, attrs) => { - if (state.isRootNode) { state.isRootNode = false; } - state.currentPath = state.currentPath + "/" + name; - checkForResourcePath(name); - if (state.isPathfound) { processStartElement(name, attrs); } - }); - - parser.on("endElement", (name) => { - state.lastEndedNode = name; - lastIndex = state.currentPath.lastIndexOf("/" + name); - if (state.currentPath.substring(lastIndex + 1).indexOf("/") !== -1) { - processError.call(this, `mismatched tag`); + parser.on('startElement', (name, attrs) => { + if (state.isRootNode) { + state.isRootNode = false } - state.currentPath = state.currentPath.substring(0, lastIndex); - if (state.isPathfound) { processEndElement(name); } - checkForResourcePath(name); - }); + state.currentPath = state.currentPath + '/' + name + checkForResourcePath(name) + if (state.isPathfound) { + processStartElement(name, attrs) + } + }) - parser.on("text", (text) => { - if (state.isPathfound) { processText(text); } - }); + parser.on('endElement', (name) => { + state.lastEndedNode = name + lastIndex = state.currentPath.lastIndexOf('/' + name) + if (state.currentPath.substring(lastIndex + 1).indexOf('/') !== -1) { + processError.call(this, `mismatched tag`) + } + state.currentPath = state.currentPath.substring(0, lastIndex) + if (state.isPathfound) { + processEndElement(name) + } + checkForResourcePath(name) + }) - parser.on("error", function(err) { - processError.call(this, err); - }); + parser.on('text', (text) => { + if (state.isPathfound) { + processText(text) + } + }) + + parser.on('error', function (err) { + processError.call(this, err) + }) function processStartElement(name: string, attrs: any) { - if (!name) { return; } - - const obj: any = {}; - if (attrs && !_.isEmpty(attrs)) { obj[attrsKey] = attrs; } - let tempObj = state.object; - const path = getRelativePath(/*name*/); - if (!path) { - if (attrs && !_.isEmpty(attrs)) { state.object[attrsKey] = attrs; } - return; + if (!name) { + return } - const tokens = path.split("."); + + const obj: any = {} + if (attrs && !_.isEmpty(attrs)) { + obj[attrsKey] = attrs + } + let tempObj = state.object + const path = getRelativePath(/*name*/) + if (!path) { + if (attrs && !_.isEmpty(attrs)) { + state.object[attrsKey] = attrs + } + return + } + const tokens = path.split('.') for (let i = 0; i < tokens.length; i++) { if (tempObj[tokens[i]] && !(explicitArray === false && i === tokens.length - 1)) { - tempObj = tempObj[tokens[i]]; + tempObj = tempObj[tokens[i]] } else { // if explicitArray is true then create each node as array // irrespective of how many nodes are there with same name. - tempObj[tokens[i]] = explicitArray ? [] : obj; - tempObj = tempObj[tokens[i]]; + tempObj[tokens[i]] = explicitArray ? [] : obj + tempObj = tempObj[tokens[i]] + } + if (Array.isArray(tempObj) && i !== tokens.length - 1) { + tempObj = tempObj[tempObj.length - 1] } - if (Array.isArray(tempObj) && i !== tokens.length - 1) { tempObj = tempObj[tempObj.length - 1]; } } if (Array.isArray(tempObj)) { - tempObj.push(obj); + tempObj.push(obj) } } function processEndElement(name: string) { if (resourcePath) { - const index = resourcePath.lastIndexOf("/"); - const rpath = resourcePath.substring(0, index); + const index = resourcePath.lastIndexOf('/') + const rpath = resourcePath.substring(0, index) if (rpath === state.currentPath) { - scope.push(state.object); - if (scope.opts.emitOnNodeName) { scope.emit(name, state.object); } - state.object = {}; + scope.push(state.object) + if (scope.opts.emitOnNodeName) { + scope.emit(name, state.object) + } + state.object = {} } } else { if (_.includes(interestedNodes, name, 0)) { - emitInterestedNode(name); + emitInterestedNode(name) if (state.firstFoundNode === name) { - state.object = {}; - state.firstFoundNode = ""; - state.isPathfound = false; + state.object = {} + state.firstFoundNode = '' + state.isPathfound = false } } } } function emitInterestedNode(name: string) { - let index; - let xpath; - let pathTokens; + let index + let xpath + let pathTokens - xpath = state.currentPath.substring(1); - pathTokens = xpath.split("/"); - pathTokens.push(name); - index = pathTokens.indexOf(state.firstFoundNode); - pathTokens = _.drop(pathTokens, index + 1); - let tempObj = state.object; + xpath = state.currentPath.substring(1) + pathTokens = xpath.split('/') + pathTokens.push(name) + index = pathTokens.indexOf(state.firstFoundNode) + pathTokens = _.drop(pathTokens, index + 1) + let tempObj = state.object // tslint:disable-next-line:prefer-for-of for (let i = 0; i < pathTokens.length; i++) { - tempObj = tempObj[pathTokens[i] as any]; + tempObj = tempObj[pathTokens[i] as any] + } + if (Array.isArray(tempObj)) { + tempObj = tempObj[tempObj.length - 1] } - if (Array.isArray(tempObj)) { tempObj = tempObj[tempObj.length - 1]; } - scope.emit(name, tempObj); - scope.push(tempObj); + scope.emit(name, tempObj) + scope.push(tempObj) } function processText(text: string) { - if ((!text) || ((!verbatimText) && !/\S/.test(text))) { - return; + if (!text || (!verbatimText && !/\S/.test(text))) { + return } - const path = getRelativePath(); - let tempObj = state.object; + const path = getRelativePath() + let tempObj = state.object if (!path) { - if (!state.object[textKey]) { state.object[textKey] = ""; } - state.object[textKey] = state.object[textKey] + text; - if ((!preserveWhitespace)) { - state.object[textKey] = state.object[textKey].replace(/\s+/g, " ").trim(); + if (!state.object[textKey]) { + state.object[textKey] = '' } - return; + state.object[textKey] = state.object[textKey] + text + if (!preserveWhitespace) { + state.object[textKey] = state.object[textKey].replace(/\s+/g, ' ').trim() + } + return } - const tokens = path.split("."); + const tokens = path.split('.') for (let i = 0; i < tokens.length; i++) { if (tempObj[tokens[i]]) { - tempObj = tempObj[tokens[i]]; + tempObj = tempObj[tokens[i]] } else { - tempObj[tokens[i]] = explicitArray ? [] : {}; - tempObj = tempObj[tokens[i]]; + tempObj[tokens[i]] = explicitArray ? [] : {} + tempObj = tempObj[tokens[i]] + } + if (Array.isArray(tempObj) && i !== tokens.length - 1) { + tempObj = tempObj[tempObj.length - 1] } - if (Array.isArray(tempObj) && i !== tokens.length - 1) { tempObj = tempObj[tempObj.length - 1]; } } if (Array.isArray(tempObj)) { - const obj = tempObj[tempObj.length - 1]; - if (!obj[textKey]) { obj[textKey] = ""; } - obj[textKey] = obj[textKey] + text; - - if ((!preserveWhitespace)) { - obj[textKey] = obj[textKey].replace(/\s+/g, " ").trim(); + const obj = tempObj[tempObj.length - 1] + if (!obj[textKey]) { + obj[textKey] = '' } + obj[textKey] = obj[textKey] + text + if (!preserveWhitespace) { + obj[textKey] = obj[textKey].replace(/\s+/g, ' ').trim() + } } else { - if (!tempObj[textKey]) { tempObj[textKey] = ""; } - tempObj[textKey] = tempObj[textKey] + text; + if (!tempObj[textKey]) { + tempObj[textKey] = '' + } + tempObj[textKey] = tempObj[textKey] + text - if ((!preserveWhitespace)) { - tempObj[textKey] = tempObj[textKey].replace(/\s+/g, " ").trim(); + if (!preserveWhitespace) { + tempObj[textKey] = tempObj[textKey].replace(/\s+/g, ' ').trim() } } - } function checkForResourcePath(name: string) { if (resourcePath) { if (state.currentPath.indexOf(resourcePath) === 0) { - state.isPathfound = true; + state.isPathfound = true } else { - state.isPathfound = false; + state.isPathfound = false } } else { if (_.includes(interestedNodes, name, 0)) { - state.isPathfound = true; + state.isPathfound = true if (!state.firstFoundNode) { - state.firstFoundNode = name; + state.firstFoundNode = name } } } } function getRelativePath() { - let tokens; - let jsonPath; - let index; + let tokens + let jsonPath + let index if (resourcePath) { - let xpath = state.currentPath.substring(resourcePath.length); + let xpath = state.currentPath.substring(resourcePath.length) - if (!xpath) { return; } - if (xpath[0] === "/") { xpath = xpath.substring(1); } - tokens = xpath.split("/"); - jsonPath = tokens.join("."); + if (!xpath) { + return + } + if (xpath[0] === '/') { + xpath = xpath.substring(1) + } + tokens = xpath.split('/') + jsonPath = tokens.join('.') } else { - const xpath = state.currentPath.substring(1); - tokens = xpath.split("/"); - index = tokens.indexOf(state.firstFoundNode); - tokens = _.drop(tokens, index + 1); - jsonPath = tokens.join("."); + const xpath = state.currentPath.substring(1) + tokens = xpath.split('/') + index = tokens.indexOf(state.firstFoundNode) + tokens = _.drop(tokens, index + 1) + jsonPath = tokens.join('.') } - return jsonPath; + return jsonPath } } function processError(err: Error) { - const parser = this.parser; - let error: Error = null; + const parser = this.parser + let error: Error = null if (err) { - error = err; + error = err } else { - error = parser.getError(); + error = parser.getError() } - error = new Error(`${error} at line no: ${parser.getCurrentLineNumber()}`); - this.emit("error", error); - return error; + error = new Error(`${error} at line no: ${parser.getCurrentLineNumber()}`) + this.emit('error', error) + return error } diff --git a/src/parserState.ts b/src/parserState.ts index ac4856a..5c11073 100644 --- a/src/parserState.ts +++ b/src/parserState.ts @@ -1,11 +1,10 @@ - export class ParserState { - public currentPath = ""; - public lastEndedNode = ""; - public isPathfound = false; - public object: any = {}; - public paused = false; - public isRootNode = true; - public firstFoundNode = ""; - public interestedNodes: string[] = []; + public currentPath = '' + public lastEndedNode = '' + public isPathfound = false + public object: any = {} + public paused = false + public isRootNode = true + public firstFoundNode = '' + public interestedNodes: string[] = [] } diff --git a/src/unescape.ts b/src/unescape.ts index c941261..18e8e4d 100644 --- a/src/unescape.ts +++ b/src/unescape.ts @@ -1,83 +1,86 @@ - -const escapeXMLTable: {[char: string]: string} = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'" -}; - -function escapeXMLReplace(match: string) { - return escapeXMLTable[match]; +const escapeXMLTable: { [char: string]: string } = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' } -const unescapeXMLTable: {[char: string]: string} = { - "&": "&", - "<": "<", - ">": ">", - """: '"', - "'": "'" -}; +function escapeXMLReplace(match: string) { + return escapeXMLTable[match] +} + +const unescapeXMLTable: { [char: string]: string } = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" +} function unescapeXMLReplace(match: string) { - if (match[1] === "#") { - let num; - if (match[2] === "x") { - num = parseInt(match.slice(3), 16); + if (match[1] === '#') { + let num + if (match[2] === 'x') { + num = parseInt(match.slice(3), 16) } else { - num = parseInt(match.slice(2), 10); + num = parseInt(match.slice(2), 10) } // https://www.w3.org/TR/xml/#NT-Char defines legal XML characters: // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] - if (num === 0x9 || num === 0xA || num === 0xD || - (num >= 0x20 && num <= 0xD7FF) || - (num >= 0xE000 && num <= 0xFFFD) || - (num >= 0x10000 && num <= 0x10FFFF)) { - return String.fromCodePoint(num); + if ( + num === 0x9 || + num === 0xa || + num === 0xd || + (num >= 0x20 && num <= 0xd7ff) || + (num >= 0xe000 && num <= 0xfffd) || + (num >= 0x10000 && num <= 0x10ffff) + ) { + return String.fromCodePoint(num) } - throw new Error("Illegal XML character 0x" + num.toString(16)); + throw new Error('Illegal XML character 0x' + num.toString(16)) } if (unescapeXMLTable[match]) { - return unescapeXMLTable[match] || match; + return unescapeXMLTable[match] || match } - throw new Error("Illegal XML entity " + match); + throw new Error('Illegal XML entity ' + match) } export function escapeXML(s: string) { - return s.replace(/&|<|>|"|'/g, escapeXMLReplace); + return s.replace(/&|<|>|"|'/g, escapeXMLReplace) } export function unescapeXML(s: string) { - let result = ""; - let start = -1; - let end = -1; - let previous = 0; - start = s.indexOf("&", previous); - end = s.indexOf(";", start + 1); + let result = '' + let start = -1 + let end = -1 + let previous = 0 + start = s.indexOf('&', previous) + end = s.indexOf(';', start + 1) - while ((start !== -1) && (end !== -1 )) { - result = result + - s.substring(previous, start) + - unescapeXMLReplace(s.substring(start, end + 1)); - previous = end + 1; - start = s.indexOf("&", previous); - end = s.indexOf(";", start + 1); + while (start !== -1 && end !== -1) { + result = result + s.substring(previous, start) + unescapeXMLReplace(s.substring(start, end + 1)) + previous = end + 1 + start = s.indexOf('&', previous) + end = s.indexOf(';', start + 1) } // shortcut if loop never entered: // return the original string without creating new objects - if (previous === 0) { return s; } + if (previous === 0) { + return s + } // push the remaining characters - result = result + s.substring(previous); + result = result + s.substring(previous) - return result; + return result } export function escapeXMLText(s: string) { - return s.replace(/&|<|>/g, escapeXMLReplace); + return s.replace(/&|<|>/g, escapeXMLReplace) } export function unescapeXMLText(s: string) { - return s.replace(/&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace); + return s.replace(/&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace) } diff --git a/test/basic.spec.ts b/test/basic.spec.ts index 4e80683..8ac3ba6 100644 --- a/test/basic.spec.ts +++ b/test/basic.spec.ts @@ -1,146 +1,153 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("Basic behavior", () => { - it("should properly parse a simple file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +describe('Basic behavior', () => { + it('should properly parse a simple file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualData: string[] = []; - let dataEventCount = 0; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a medium size file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a medium size file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) - let dataEventCount = 0; + let dataEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(10); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(10) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a file containing many nodes.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a file containing many nodes.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) - let dataEventCount = 0; + let dataEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(296); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(296) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a xml simple file in which nodes contain text values randomly.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/randomText.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - const 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" }] - } - ]; - const actualData: string[] = []; - let dataEventCount = 0; + it('should properly parse a xml simple file in which nodes contain text values randomly.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/randomText.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + const 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' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a huge file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a huge file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) // console.log(parser) - let dataEventCount = 0; - parser.on("data", (data) => { - dataEventCount++; - }); + let dataEventCount = 0 + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(2072); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(2072) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/cdata_and_comments.spec.ts b/test/cdata_and_comments.spec.ts index 75499bd..0977916 100644 --- a/test/cdata_and_comments.spec.ts +++ b/test/cdata_and_comments.spec.ts @@ -1,30 +1,30 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("CData and comments in xml", () => { - it("should properly parse a simple file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/CData-comments.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +import { XmlParser } from '../src/parser' +describe('CData and comments in xml', () => { + it('should properly parse a simple file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/CData-comments.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) - let dataEventCount = 0; + let dataEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(296); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(296) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/emit.spec.ts b/test/emit.spec.ts index ee19474..c39ab0b 100644 --- a/test/emit.spec.ts +++ b/test/emit.spec.ts @@ -1,136 +1,138 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("emitOnNodeName", () => { - it("should properly emit events on node names.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", emitOnNodeName: true }); +import { XmlParser } from '../src/parser' +describe('emitOnNodeName', () => { + it('should properly emit events on node names.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item', emitOnNodeName: true }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualData: string[] = []; - const itemData : string[] = []; - let dataEventCount = 0; - let itemCount = 0; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualData: string[] = [] + const itemData: string[] = [] + let dataEventCount = 0 + let itemCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("item", (item) => { - itemData.push(item); - itemCount++; - }); + parser.on('item', (item) => { + itemData.push(item) + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - should(itemData).deepEqual(expectedData); - should(itemCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + should(itemData).deepEqual(expectedData) + should(itemCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly emit events on node names while parsing a medium size file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", emitOnNodeName: true }); + it('should properly emit events on node names while parsing a medium size file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item', emitOnNodeName: true }) - let dataEventCount = 0; - let itemCount = 0; + let dataEventCount = 0 + let itemCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("item", (data) => { - itemCount++; - }); + parser.on('item', (data) => { + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(10); - should(itemCount).equal(10); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(10) + should(itemCount).equal(10) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a file containing many nodes.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", emitOnNodeName: true }); + it('should properly parse a file containing many nodes.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/items/item', emitOnNodeName: true }) - let dataEventCount = 0; - let itemCount = 0; - parser.on("data", (data) => { - dataEventCount++; - }); + let dataEventCount = 0 + let itemCount = 0 + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("item", (data) => { - itemCount++; - }); + parser.on('item', (data) => { + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(296); - should(itemCount).equal(296); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(296) + should(itemCount).equal(296) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a huge file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", emitOnNodeName: true }); + it('should properly parse a huge file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item', emitOnNodeName: true }) - let dataEventCount = 0; - let itemCount = 0; + let dataEventCount = 0 + let itemCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("item", (item) => { - itemCount++; - }); + parser.on('item', (item) => { + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(2072); - should(itemCount).equal(2072); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(2072) + should(itemCount).equal(2072) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/error.spec.ts b/test/error.spec.ts index 8d3e7d5..3fb1ea2 100644 --- a/test/error.spec.ts +++ b/test/error.spec.ts @@ -1,45 +1,44 @@ +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import { XmlParser } from '../src/parser' +describe.skip('Error Handling', () => { + it('should properly return error if the xml file is corrupted.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/corrupted.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + let dataEventCount = 0 -import { XmlParser } from "../src/parser"; -describe.skip("Error Handling", () => { - it("should properly return error if the xml file is corrupted.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/corrupted.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - let dataEventCount = 0; + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("data", (data) => { - dataEventCount++; - }); - - parser.on("error", (err) => { + parser.on('error', (err) => { // console.log(err) - should(err.message).equal("mismatched tag at line no: 12"); - done(); - }); + should(err.message).equal('mismatched tag at line no: 12') + done() + }) - xmlStream.pipe(parser); - }); + xmlStream.pipe(parser) + }) - it("should properly return error if the large xml file is corrupted.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/largeCorruptedFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - let dataEventCount = 0; + it('should properly return error if the large xml file is corrupted.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/largeCorruptedFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + let dataEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { + parser.on('error', (err) => { // console.log(err) - should(err.message).equal("mismatched tag at line no: 8346"); - done(); - }); + should(err.message).equal('mismatched tag at line no: 8346') + done() + }) - xmlStream.pipe(parser); - }); -}); + xmlStream.pipe(parser) + }) +}) diff --git a/test/explicit_array.spec.ts b/test/explicit_array.spec.ts index b4809c9..ff5632c 100644 --- a/test/explicit_array.spec.ts +++ b/test/explicit_array.spec.ts @@ -1,250 +1,270 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("should respect explicitArray constructor option", () => { - it("should properly parse a simple file with explicitArray set to false.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); +import { XmlParser } from '../src/parser' +describe('should respect explicitArray constructor option', () => { + it('should properly parse a simple file with explicitArray set to false.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: { $: { sub: "2" }, _: "two" } + $: { id: '1', test: 'hello' }, + subitem: { $: { sub: '2' }, _: 'two' } }, { - $: { id: "2" }, - subitem: { _: "five" } - }]; + $: { id: '2' }, + subitem: { _: 'five' } + } + ] parser.parse(xml.toString(), (err, data) => { - if (err) { done(err); } + if (err) { + done(err) + } // console.log('data=', JSON.stringify(data)) - should(data).deepEqual(expectedData); - done(); - }); - }); + should(data).deepEqual(expectedData) + done() + }) + }) - it("should properly parse a medium size file with explicitArray set to false.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); + it('should properly parse a medium size file with explicitArray set to false.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) const expectedData = [ { $: { - id: "1", - test: "hello" + id: '1', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "2" + id: '2' }, subitem: { - _: "five" + _: 'five' } }, { $: { - id: "3", - test: "hello" + id: '3', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "4", - test: "hello" + id: '4', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "5", - test: "hello" + id: '5', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "6", - test: "hello" + id: '6', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "7", - test: "hello" + id: '7', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "8", - test: "hello" + id: '8', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "9", - test: "hello" + id: '9', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } }, { $: { - id: "10", - test: "hello" + id: '10', + test: 'hello' }, subitem: { $: { - sub: "2" + sub: '2' }, - _: "two" + _: 'two' } } - ]; + ] parser.parse(xml, (err, data) => { - if (err) { done(err); } + if (err) { + done(err) + } - should(data).deepEqual(expectedData); - should(data.length).equal(10); - done(); - }); - }); + should(data).deepEqual(expectedData) + should(data.length).equal(10) + done() + }) + }) - it("should properly parse a file containing many nodes when explicitArray set to false.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); + it('should properly parse a file containing many nodes when explicitArray set to false.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) parser.parse(xml, (err, data) => { - if (err) { done(err); } + if (err) { + done(err) + } - should(data.length).equal(296); - done(); - }); - }); + should(data.length).equal(296) + done() + }) + }) - it("should properly parse a xml simple file in which nodes contain text values randomly when explicitArray set to false.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/randomText.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); - const expectedData = [{ - $: { id: "1", test: "hello" }, _: "item one two", - subitem: { $: { sub: "2" }, _: "two" } - }, - { - $: { id: "2" }, _: "item one two three four", - subitem: { _: "five" } - } - ]; + it('should properly parse a xml simple file in which nodes contain text values randomly when explicitArray set to false.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/randomText.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) + const expectedData = [ + { + $: { id: '1', test: 'hello' }, + _: 'item one two', + subitem: { $: { sub: '2' }, _: 'two' } + }, + { + $: { id: '2' }, + _: 'item one two three four', + subitem: { _: 'five' } + } + ] parser.parse(xml, (err, data) => { - if (err) { done(err); } + if (err) { + done(err) + } - should(data).deepEqual(expectedData); - should(data.length).equal(2); - done(); - }); - }); + should(data).deepEqual(expectedData) + should(data.length).equal(2) + done() + }) + }) - it("should properly parse a huge file with explicitArray set to false.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); + it('should properly parse a huge file with explicitArray set to false.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) // console.log(parser) parser.parse(xml, (err, data) => { - if (err) { done(err); } - should(data.length).equal(2072); - done(); - }); - }); + if (err) { + done(err) + } + should(data.length).equal(2072) + done() + }) + }) - it("should properly return error if the xml file is corrupted.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/corrupted.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", explicitArray: false }); + it('should properly return error if the xml file is corrupted.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/corrupted.xml') + const parser = new XmlParser({ resourcePath: '/items/item', explicitArray: false }) parser.parse(xml, (err, data) => { // console.log(err) - should(err.message).equal("mismatched tag at line no: 12"); - should(data).not.be.ok(); - done(); - }); - }); + should(err.message).equal('mismatched tag at line no: 12') + should(data).not.be.ok() + done() + }) + }) - it("should properly generate objects when special symbols are passed as attrs and text keys and explicitArray is false in the options.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", attrsKey: "!", textKey: "%", explicitArray: false }); + it('should properly generate objects when special symbols are passed as attrs and text keys and explicitArray is false in the options.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ + resourcePath: '/items/item', + attrsKey: '!', + textKey: '%', + explicitArray: false + }) const expectedData = [ { - "!": { id: "1", test: "hello" }, - "subitem": { "!": { sub: "2" }, "%": "two" } + '!': { id: '1', test: 'hello' }, + subitem: { '!': { sub: '2' }, '%': 'two' } }, { - "!": { id: "2" }, - "subitem": { "%": "five" } - }]; - const actualData: string[] = []; - let dataEventCount = 0; + '!': { id: '2' }, + subitem: { '%': 'five' } + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/interested.spec.ts b/test/interested.spec.ts index f719b2b..0419353 100644 --- a/test/interested.spec.ts +++ b/test/interested.spec.ts @@ -1,321 +1,336 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("interested Nodes", () => { - it("should properly parse a simple file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser(); +describe('interested Nodes', () => { + it('should properly parse a simple file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser() - const expectedData = - [ - { $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }, - { - $: { id: "1", test: "hello" }, - subitem: [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] - }, - { _: "three" }, - { _: "four" }, - { _: "five" }, - { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - } - ]; + const expectedData = [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' }, + { + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] + }, + { _: 'three' }, + { _: 'four' }, + { _: 'five' }, + { + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] - const actualData: string[] = []; - let dataEventCount = 0; + const actualData: string[] = [] + let dataEventCount = 0 const expectedItems = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualItems: string[] = []; - const actualSubitems: string[] = []; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualItems: string[] = [] + const actualSubitems: string[] = [] const expectedSubitems = [ - { $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }, - { _: "three" }, - { _: "four" }, - { _: "five" } - ]; + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' }, + { _: 'three' }, + { _: 'four' }, + { _: 'five' } + ] - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("item", (item) => { - actualItems.push(item); - }); + parser.on('item', (item) => { + actualItems.push(item) + }) - parser.on("subitem", (subitem) => { - actualSubitems.push(subitem); - }); + parser.on('subitem', (subitem) => { + actualSubitems.push(subitem) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(actualItems).deepEqual(expectedItems); - should(actualSubitems).deepEqual(expectedSubitems); - should(actualSubitems.length).equal(5); - should(actualItems.length).equal(2); - should(dataEventCount).equal(7); - done(); - }); + should(actualData).deepEqual(expectedData) + should(actualItems).deepEqual(expectedItems) + should(actualSubitems).deepEqual(expectedSubitems) + should(actualSubitems.length).equal(5) + should(actualItems.length).equal(2) + should(dataEventCount).equal(7) + done() + }) - xmlStream.pipe(parser); - }); + xmlStream.pipe(parser) + }) - it("should properly parse a medium size file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser(); + it('should properly parse a medium size file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser() - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - }); + parser.on('item', (item) => { + itemEventCount++ + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemEventCount) // console.log('subitemEventCount=', subitemEventCount) - should(dataEventCount).equal(31); - should(itemEventCount).equal(10); - should(subitemEventCount).equal(21); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(31) + should(itemEventCount).equal(10) + should(subitemEventCount).equal(21) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a file containing many nodes.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser(); + it('should properly parse a file containing many nodes.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/manyItems.xml') + const parser = new XmlParser() - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - }); + parser.on('item', (item) => { + itemEventCount++ + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemEventCount) // console.log('subitemEventCount=', subitemEventCount) - should(itemEventCount).equal(296); - should(subitemEventCount).equal(600); - should(dataEventCount).equal(896); - done(); - }); - xmlStream.pipe(parser); - }); + should(itemEventCount).equal(296) + should(subitemEventCount).equal(600) + should(dataEventCount).equal(896) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a xml simple file in which nodes contain text values randomly.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/randomText.xml"); - const parser = new XmlParser(); - const expectedData = - [ - { $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }, - { - $: { id: "1", test: "hello" }, _: "item one two", - subitem: [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] - }, - { _: "three" }, - { _: "four" }, - { _: "five" }, - { - $: { id: "2" }, _: "item one two three four", - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - } - ]; + it('should properly parse a xml simple file in which nodes contain text values randomly.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/randomText.xml') + const parser = new XmlParser() + const expectedData = [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' }, + { + $: { id: '1', test: 'hello' }, + _: 'item one two', + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] + }, + { _: 'three' }, + { _: 'four' }, + { _: 'five' }, + { + $: { id: '2' }, + _: 'item one two three four', + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] const expectedItems = [ { - $: { id: "1", test: "hello" }, _: "item one two", - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { 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" }] - }]; - const actualItems: string[] = []; - const actualSubitems: string[] = []; + $: { id: '2' }, + _: 'item one two three four', + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualItems: string[] = [] + const actualSubitems: string[] = [] const expectedSubitems = [ - { $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }, - { _: "three" }, - { _: "four" }, - { _: "five" } - ]; - const actualData: string[] = []; - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' }, + { _: 'three' }, + { _: 'four' }, + { _: 'five' } + ] + const actualData: string[] = [] + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - actualItems.push(item); - }); + parser.on('item', (item) => { + itemEventCount++ + actualItems.push(item) + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - actualSubitems.push(subitem); - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + actualSubitems.push(subitem) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemEventCount) // console.log('subitemEventCount=', subitemEventCount) - should(actualData).deepEqual(expectedData); - should(actualItems).deepEqual(expectedItems); - should(actualSubitems).deepEqual(expectedSubitems); - should(dataEventCount).equal(7); - should(itemEventCount).equal(2); - should(subitemEventCount).equal(5); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(actualItems).deepEqual(expectedItems) + should(actualSubitems).deepEqual(expectedSubitems) + should(dataEventCount).equal(7) + should(itemEventCount).equal(2) + should(subitemEventCount).equal(5) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a huge file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser(); + it('should properly parse a huge file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser() - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - }); + parser.on('item', (item) => { + itemEventCount++ + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemEventCount) // console.log('subitemEventCount=', subitemEventCount) - should(dataEventCount).equal(6272); - should(itemEventCount).equal(2072); - should(subitemEventCount).equal(4200); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(6272) + should(itemEventCount).equal(2072) + should(subitemEventCount).equal(4200) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a simple file and return when root element when listening on it.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser(); - const expectedData = - [{ - item: [{ - $: { id: "1", test: "hello" }, - subitem: [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] - }, - { - $: { id: "2" }, subitem: [{ _: "three" }, { _: "four" }, - { _: "five" }] - }] - }]; + it('should properly parse a simple file and return when root element when listening on it.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser() + const expectedData = [ + { + item: [ + { + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] + }, + { + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + } + ] - const actualData: string[] = []; - let dataEventCount = 0; - let itemsEventCount = 0; + const actualData: string[] = [] + let dataEventCount = 0 + let itemsEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("items", (item) => { - itemsEventCount++; - }); + parser.on('items', (item) => { + itemsEventCount++ + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemsEventCount) - should(actualData).deepEqual(expectedData); - should(itemsEventCount).equal(1); - should(dataEventCount).equal(1); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(actualData).deepEqual(expectedData) + should(itemsEventCount).equal(1) + should(dataEventCount).equal(1) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/options.spec.ts b/test/options.spec.ts index 0ab70ab..88b9eb7 100644 --- a/test/options.spec.ts +++ b/test/options.spec.ts @@ -1,117 +1,123 @@ -import fs from "fs"; -import "mocha"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("should respect the options passed", () => { - it("should properly generate objects with $ as key for attrs and _ as key for text value of node.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +import { XmlParser } from '../src/parser' +describe('should respect the options passed', () => { + it('should properly generate objects with $ as key for attrs and _ as key for text value of node.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualData: string[] = []; - let dataEventCount = 0; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly generate objects with passed attrs and text keys in the options.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", attrsKey: "attrs", textKey: "text" }); + it('should properly generate objects with passed attrs and text keys in the options.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item', attrsKey: 'attrs', textKey: 'text' }) const expectedData = [ { - attrs: { id: "1", test: "hello" }, - subitem: - [{ attrs: { sub: "TESTING SUB" }, text: "one" }, - { attrs: { sub: "2" }, text: "two" }] + attrs: { id: '1', test: 'hello' }, + subitem: [ + { attrs: { sub: 'TESTING SUB' }, text: 'one' }, + { attrs: { sub: '2' }, text: 'two' } + ] }, { - attrs: { id: "2" }, - subitem: [{ text: "three" }, { text: "four" }, { text: "five" }] - }]; - const actualData: string[] = []; - let dataEventCount = 0; + attrs: { id: '2' }, + subitem: [{ text: 'three' }, { text: 'four' }, { text: 'five' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly generate objects when special symbols are passed as attrs and text keys in the options.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item", attrsKey: "!", textKey: "%" }); + it('should properly generate objects when special symbols are passed as attrs and text keys in the options.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item', attrsKey: '!', textKey: '%' }) const expectedData = [ { - "!": { id: "1", test: "hello" }, - "subitem": - [{ "!": { sub: "TESTING SUB" }, "%": "one" }, - { "!": { sub: "2" }, "%": "two" }] + '!': { id: '1', test: 'hello' }, + subitem: [ + { '!': { sub: 'TESTING SUB' }, '%': 'one' }, + { '!': { sub: '2' }, '%': 'two' } + ] }, { - "!": { id: "2" }, - "subitem": [{ "%": "three" }, { "%": "four" }, { "%": "five" }] - }]; - const actualData: string[] = []; - let dataEventCount = 0; + '!': { id: '2' }, + subitem: [{ '%': 'three' }, { '%': 'four' }, { '%': 'five' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', JSON.stringify(actualData, null, 1)) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/parse.spec.ts b/test/parse.spec.ts index 8092e6d..6c62659 100644 --- a/test/parse.spec.ts +++ b/test/parse.spec.ts @@ -1,97 +1,114 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("Parse function should work properly", () => { - it("should properly parse a simple file.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +import { XmlParser } from '../src/parser' +describe('Parse function should work properly', () => { + it('should properly parse a simple file.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] parser.parse(xml.toString(), (err, data) => { - if (err) { done(err); } - should(data).deepEqual(expectedData); - done(); - }); - }); + if (err) { + done(err) + } + should(data).deepEqual(expectedData) + done() + }) + }) - it("should properly parse a medium size file.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a medium size file.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) parser.parse(xml, (err, data) => { - if (err) { done(err); } - should(data.length).equal(10); - done(); - }); - }); + if (err) { + done(err) + } + should(data.length).equal(10) + done() + }) + }) - it("should properly parse a file containing many nodes.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a file containing many nodes.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) parser.parse(xml, (err, data) => { - if (err) { done(err); } - should(data.length).equal(296); - done(); - }); - }); + if (err) { + done(err) + } + should(data.length).equal(296) + done() + }) + }) - it("should properly parse a xml simple file in which nodes contain text values randomly.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/randomText.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - const 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" }] - } - ]; + it('should properly parse a xml simple file in which nodes contain text values randomly.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/randomText.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + const 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, (err, data) => { - if (err) { done(err); } - should(data).deepEqual(expectedData); - should(data.length).equal(2); - done(); - }); - }); + if (err) { + done(err) + } + should(data).deepEqual(expectedData) + should(data.length).equal(2) + done() + }) + }) - it("should properly parse a huge file.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse a huge file.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) // console.log(parser) parser.parse(xml, (err, data) => { - if (err) { done(err); } - should(data.length).equal(2072); - done(); - }); - }); + if (err) { + done(err) + } + should(data.length).equal(2072) + done() + }) + }) - it("should properly return error if the xml file is corrupted.", (done) => { - const xml = fs.readFileSync("./test/TestFiles/corrupted.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly return error if the xml file is corrupted.', (done) => { + const xml = fs.readFileSync('./test/TestFiles/corrupted.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) parser.parse(xml, (err, data) => { // console.log(err) - should(err.message).equal("mismatched tag at line no: 12"); - should(data).not.be.ok(); - done(); - }); - }); -}); + should(err.message).equal('mismatched tag at line no: 12') + should(data).not.be.ok() + done() + }) + }) +}) diff --git a/test/pause_and_resume.spec.ts b/test/pause_and_resume.spec.ts index 1934acb..41bc3bf 100644 --- a/test/pause_and_resume.spec.ts +++ b/test/pause_and_resume.spec.ts @@ -1,82 +1,84 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; -describe("pause and resume", () => { - it("should properly parse a simple file.", function(done) { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +import { XmlParser } from '../src/parser' +describe('pause and resume', () => { + it('should properly parse a simple file.', function (done) { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualData: string[] = []; - let dataEventCount = 0; - let isSetTimeoutHappened = true; - this.timeout(4000); - parser.on("data", (data) => { - actualData.push(data); - parser.pause(); - should(isSetTimeoutHappened).equal(true); + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualData: string[] = [] + let dataEventCount = 0 + let isSetTimeoutHappened = true + this.timeout(4000) + parser.on('data', (data) => { + actualData.push(data) + parser.pause() + should(isSetTimeoutHappened).equal(true) setTimeout(() => { - parser.resume(); - isSetTimeoutHappened = true; - }, 1000); - dataEventCount++; - isSetTimeoutHappened = false; - }); + parser.resume() + isSetTimeoutHappened = true + }, 1000) + dataEventCount++ + isSetTimeoutHappened = false + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - should(actualData).deepEqual(expectedData); - should(dataEventCount).equal(2); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData).deepEqual(expectedData) + should(dataEventCount).equal(2) + done() + }) + xmlStream.pipe(parser) + }) - it("should emit data events with 1sec interval between each using pause and resume.", function(done) { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should emit data events with 1sec interval between each using pause and resume.', function (done) { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) - let dataEventCount = 0; - let isSetTimeoutHappened = true; - this.timeout(20000); - parser.on("data", (data) => { - parser.pause(); - should(isSetTimeoutHappened).equal(true); + let dataEventCount = 0 + let isSetTimeoutHappened = true + this.timeout(20000) + parser.on('data', (data) => { + parser.pause() + should(isSetTimeoutHappened).equal(true) setTimeout(() => { - parser.resume(); - isSetTimeoutHappened = true; - }, 1000); - dataEventCount++; - isSetTimeoutHappened = false; - }); + parser.resume() + isSetTimeoutHappened = true + }, 1000) + dataEventCount++ + isSetTimeoutHappened = false + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(10); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(10) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/performance.spec.ts b/test/performance.spec.ts index fe714be..1667dfc 100644 --- a/test/performance.spec.ts +++ b/test/performance.spec.ts @@ -1,103 +1,102 @@ +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; - -import { XmlParser } from "../src/parser"; -describe.skip("performance testing", () => { - it("should properly parse more than 500 MB of file.", function(done) { - const parser = new XmlParser({ resourcePath: "/items/item" }); +import { XmlParser } from '../src/parser' +describe.skip('performance testing', () => { + it('should properly parse more than 500 MB of file.', function (done) { + const parser = new XmlParser({ resourcePath: '/items/item' }) // var wsStream = fs.createWriteStream('./test/TestFiles/MB_and_GB_size_files/MBFile.xml') // var rsStream = fs.createReadStream('./test/TestFiles/MB_and_GB_size_files/MBFile.xml') - let dataEventCount = 0; + let dataEventCount = 0 // var maxRSSMemoryTaken = 0 // var rss - const startTime = Date.now(); - const xmlStream = new stream.Readable(); + const startTime = Date.now() + const xmlStream = new stream.Readable() xmlStream._read = function noop() { // nop - }; - let dataChunk; - this.timeout(900000); - const firstChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/firstChunk.xml"); - xmlStream.push(firstChunk); + } + let dataChunk + this.timeout(900000) + const firstChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/firstChunk.xml') + xmlStream.push(firstChunk) for (let i = 0; i < 2200; i++) { - dataChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/repetitiveChunk.xml"); - xmlStream.push(dataChunk); + dataChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/repetitiveChunk.xml') + xmlStream.push(dataChunk) } - const endingChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/endingChunk.xml"); - xmlStream.push(endingChunk); - xmlStream.push(null); - parser.on("data", (data) => { + const endingChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/endingChunk.xml') + xmlStream.push(endingChunk) + xmlStream.push(null) + parser.on('data', (data) => { // rss = process.memoryUsage().rss // if (rss > maxRSSMemoryTaken) maxRSSMemoryTaken = rss - dataEventCount++; - }); + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('RSS memory=', rss) - const TimeTaken = Date.now() - startTime; + const TimeTaken = Date.now() - startTime // console.log('time taken=', TimeTaken) - should(TimeTaken).be.belowOrEqual(300000); - should(dataEventCount).equal(4558400); - done(); - }); - xmlStream.pipe(parser); - }); + should(TimeTaken).be.belowOrEqual(300000) + should(dataEventCount).equal(4558400) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse more than 1 GB of file.", function(done) { - const parser = new XmlParser({ resourcePath: "/items/item" }); + it('should properly parse more than 1 GB of file.', function (done) { + const parser = new XmlParser({ resourcePath: '/items/item' }) // var wsStream = fs.createWriteStream('./test/TestFiles/MB_and_GB_size_files/MBFile.xml') // var rsStream = fs.createReadStream('./test/TestFiles/MB_and_GB_size_files/MBFile.xml') - let dataEventCount = 0; + let dataEventCount = 0 // var maxRSSMemoryTaken = 0 // var rss - const startTime = Date.now(); - const xmlStream = new stream.Readable(); + const startTime = Date.now() + const xmlStream = new stream.Readable() xmlStream._read = function noop() { // nop - }; - let dataChunk; - this.timeout(900000); - const firstChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/firstChunk.xml"); - xmlStream.push(firstChunk); + } + let dataChunk + this.timeout(900000) + const firstChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/firstChunk.xml') + xmlStream.push(firstChunk) for (let i = 0; i < 4400; i++) { - dataChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/repetitiveChunk.xml"); - xmlStream.push(dataChunk); + dataChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/repetitiveChunk.xml') + xmlStream.push(dataChunk) } - const endingChunk = fs.readFileSync("./test/TestFiles/MB_and_GB_size_files/endingChunk.xml"); - xmlStream.push(endingChunk); - xmlStream.push(null); - parser.on("data", (data) => { + const endingChunk = fs.readFileSync('./test/TestFiles/MB_and_GB_size_files/endingChunk.xml') + xmlStream.push(endingChunk) + xmlStream.push(null) + parser.on('data', (data) => { // rss = process.memoryUsage().rss // if (rss > maxRSSMemoryTaken) maxRSSMemoryTaken = rss - dataEventCount++; - }); + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('RSS memory=', rss) - const TimeTaken = Date.now() - startTime; + const TimeTaken = Date.now() - startTime // console.log('time taken=', TimeTaken) - should(TimeTaken).be.belowOrEqual(700000); - should(dataEventCount).equal(9116800); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(TimeTaken).be.belowOrEqual(700000) + should(dataEventCount).equal(9116800) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/read.spec.ts b/test/read.spec.ts index 86979bc..4b714ca 100644 --- a/test/read.spec.ts +++ b/test/read.spec.ts @@ -1,107 +1,117 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("read method", () => { - it("should properly parse a simple file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); +describe('read method', () => { + it('should properly parse a simple file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) const expectedData = [ { - $: { id: "1", test: "hello" }, - subitem: - [{ $: { sub: "TESTING SUB" }, _: "one" }, - { $: { sub: "2" }, _: "two" }] + $: { id: '1', test: 'hello' }, + subitem: [ + { $: { sub: 'TESTING SUB' }, _: 'one' }, + { $: { sub: '2' }, _: 'two' } + ] }, { - $: { id: "2" }, - subitem: [{ _: "three" }, { _: "four" }, { _: "five" }] - }]; - const actualData: string[] = []; - let obj; - let Timeout: any; + $: { id: '2' }, + subitem: [{ _: 'three' }, { _: 'four' }, { _: 'five' }] + } + ] + const actualData: string[] = [] + let obj + let Timeout: any - parser.on("readable", () => { + parser.on('readable', () => { Timeout = setInterval(() => { - obj = parser.read(); + obj = parser.read() if (obj) { - actualData.push(obj); + actualData.push(obj) } - obj = null; - }, 50); - }); + obj = null + }, 50) + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - clearInterval(Timeout); - should(actualData).deepEqual(expectedData); - done(); - }); - xmlStream.pipe(parser); - }); + clearInterval(Timeout) + should(actualData).deepEqual(expectedData) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a file containing many nodes.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - let objCount = 0; - let endEventOcurred = false; + it('should properly parse a file containing many nodes.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + let objCount = 0 + let endEventOcurred = false - parser.on("readable", () => { - read(); - }); + parser.on('readable', () => { + read() + }) function read() { - while (parser.read()) { objCount++; } - if (!endEventOcurred) { setTimeout(read, 50); } + while (parser.read()) { + objCount++ + } + if (!endEventOcurred) { + setTimeout(read, 50) + } } - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { - endEventOcurred = true; + parser.on('end', () => { + endEventOcurred = true // console.log(objCount) - should(objCount).deepEqual(296); - done(); - }); - xmlStream.pipe(parser); - }); + should(objCount).deepEqual(296) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a huge.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - let objCount = 0; - let endEventOcurred = false; + it('should properly parse a huge.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + let objCount = 0 + let endEventOcurred = false - parser.on("readable", () => { - read(); - }); + parser.on('readable', () => { + read() + }) function read() { - while (parser.read()) { objCount++; } - if (!endEventOcurred) { setTimeout(read, 50); } + while (parser.read()) { + objCount++ + } + if (!endEventOcurred) { + setTimeout(read, 50) + } } - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { - endEventOcurred = true; + parser.on('end', () => { + endEventOcurred = true // console.log(objCount); - should(objCount).deepEqual(2072); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(objCount).deepEqual(2072) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/same_name.spec.ts b/test/same_name.spec.ts index cbde5ed..051ad8b 100644 --- a/test/same_name.spec.ts +++ b/test/same_name.spec.ts @@ -1,111 +1,111 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("nodes with same names", () => { - it("should properly parse a simple file containing nodes with same names.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/nodesWithSameNames.xml"); - const parser = new XmlParser(); +describe('nodes with same names', () => { + it('should properly parse a simple file containing nodes with same names.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/nodesWithSameNames.xml') + const parser = new XmlParser() - const actualData: string[] = []; - const actualItems: string[] = []; - let dataEventCount = 0; + const actualData: string[] = [] + const actualItems: string[] = [] + let dataEventCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("item", (item) => { - actualItems.push(item); - }); + parser.on('item', (item) => { + actualItems.push(item) + }) - parser.on("end", () => { - should(actualItems.length).equal(18); - should(dataEventCount).equal(18); - done(); - }); + parser.on('end', () => { + should(actualItems.length).equal(18) + should(dataEventCount).equal(18) + done() + }) - xmlStream.pipe(parser); - }); + xmlStream.pipe(parser) + }) - it("should properly parse a simple file containing nodes with same names and emit events on multiple nodes.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/nodesWithSameNames.xml"); - const parser = new XmlParser(); + it('should properly parse a simple file containing nodes with same names and emit events on multiple nodes.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/nodesWithSameNames.xml') + const parser = new XmlParser() - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - should(err).not.be.ok(); - done(err); - }); + parser.on('error', (err) => { + should(err).not.be.ok() + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - }); + parser.on('item', (item) => { + itemEventCount++ + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + }) - parser.on("end", () => { - should(itemEventCount).equal(18); - should(subitemEventCount).equal(13); - should(dataEventCount).equal(31); - done(); - }); + parser.on('end', () => { + should(itemEventCount).equal(18) + should(subitemEventCount).equal(13) + should(dataEventCount).equal(31) + done() + }) - xmlStream.pipe(parser); - }); + xmlStream.pipe(parser) + }) - it("should properly parse a medium size file with same names randomly.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/nodesWithSameNamesRandomly.xml"); - const parser = new XmlParser(); + it('should properly parse a medium size file with same names randomly.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/nodesWithSameNamesRandomly.xml') + const parser = new XmlParser() - let dataEventCount = 0; - let itemEventCount = 0; - let subitemEventCount = 0; + let dataEventCount = 0 + let itemEventCount = 0 + let subitemEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("item", (item) => { - itemEventCount++; - }); + parser.on('item', (item) => { + itemEventCount++ + }) - parser.on("subitem", (subitem) => { - subitemEventCount++; - }); + parser.on('subitem', (subitem) => { + subitemEventCount++ + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) // console.log('itemEventCount=', itemEventCount) // console.log('subitemEventCount=', subitemEventCount) - should(dataEventCount).equal(32); - should(itemEventCount).equal(19); - should(subitemEventCount).equal(13); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(32) + should(itemEventCount).equal(19) + should(subitemEventCount).equal(13) + done() + }) + xmlStream.pipe(parser) + }) +}) diff --git a/test/uncompressed.spec.ts b/test/uncompressed.spec.ts index b823826..d63c217 100644 --- a/test/uncompressed.spec.ts +++ b/test/uncompressed.spec.ts @@ -1,64 +1,64 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("should properly handle uncompressed files", () => { - it("should properly parse a uncompressed xml file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - const gzip = zlib.createGzip(); - const gunzip = zlib.createGunzip(); - let dataEventCount = 0; +describe('should properly handle uncompressed files', () => { + it('should properly parse a uncompressed xml file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + const gzip = zlib.createGzip() + const gunzip = zlib.createGunzip() + let dataEventCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(10); - done(); - }); - xmlStream.pipe(gzip).pipe(gunzip).pipe(parser); - }); + should(dataEventCount).equal(10) + done() + }) + xmlStream.pipe(gzip).pipe(gunzip).pipe(parser) + }) - it("should properly parse uncompressed file and go fine with pause and resume.", function(done) { - const xmlStream = fs.createReadStream("./test/TestFiles/medium.xml"); - const parser = new XmlParser({ resourcePath: "/items/item" }); - const gzip = zlib.createGzip(); - const gunzip = zlib.createGunzip(); + it('should properly parse uncompressed file and go fine with pause and resume.', function (done) { + const xmlStream = fs.createReadStream('./test/TestFiles/medium.xml') + const parser = new XmlParser({ resourcePath: '/items/item' }) + const gzip = zlib.createGzip() + const gunzip = zlib.createGunzip() - let dataEventCount = 0; - let isSetTimeoutHappened = true; - this.timeout(20000); - parser.on("data", (data) => { - parser.pause(); - should(isSetTimeoutHappened).equal(true); + let dataEventCount = 0 + let isSetTimeoutHappened = true + this.timeout(20000) + parser.on('data', (data) => { + parser.pause() + should(isSetTimeoutHappened).equal(true) setTimeout(() => { - parser.resume(); - isSetTimeoutHappened = true; - }, 2000); - dataEventCount++; - isSetTimeoutHappened = false; - }); + parser.resume() + isSetTimeoutHappened = true + }, 2000) + dataEventCount++ + isSetTimeoutHappened = false + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(10); - done(); - }); - xmlStream.pipe(gzip).pipe(gunzip).pipe(parser); - }); -}); + should(dataEventCount).equal(10) + done() + }) + xmlStream.pipe(gzip).pipe(gunzip).pipe(parser) + }) +}) diff --git a/test/wrong_resourcepath.spec.ts b/test/wrong_resourcepath.spec.ts index ee548b3..ea2cb54 100644 --- a/test/wrong_resourcepath.spec.ts +++ b/test/wrong_resourcepath.spec.ts @@ -1,99 +1,99 @@ -import fs from "fs"; -import "mocha"; -import should from "should"; -import stream from "stream"; -import zlib from "zlib"; +import fs from 'fs' +import 'mocha' +import should from 'should' +import stream from 'stream' +import zlib from 'zlib' -import { XmlParser } from "../src/parser"; +import { XmlParser } from '../src/parser' -describe("wrong resourcePath", () => { - it("should be able to detect the wrong resourcePath at root level.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/item.xml"); - const parser = new XmlParser({ resourcePath: "/wrong/noNodes", emitOnNodeName: true }); +describe('wrong resourcePath', () => { + it('should be able to detect the wrong resourcePath at root level.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/item.xml') + const parser = new XmlParser({ resourcePath: '/wrong/noNodes', emitOnNodeName: true }) - const actualData : string[] = []; - const itemData : string[] = []; - let dataEventCount = 0; - let itemCount = 0; + const actualData: string[] = [] + const itemData: string[] = [] + let dataEventCount = 0 + let itemCount = 0 - parser.on("data", (data) => { - actualData.push(data); - dataEventCount++; - }); + parser.on('data', (data) => { + actualData.push(data) + dataEventCount++ + }) - parser.on("item", (item) => { - itemData.push(item); - itemCount++; - }); + parser.on('item', (item) => { + itemData.push(item) + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('actualData=', actualData) // console.log('dataEventCount=', dataEventCount) - should(actualData.length).equal(0); - should(dataEventCount).equal(0); - should(itemData.length).equal(0); - should(itemCount).equal(0); - done(); - }); - xmlStream.pipe(parser); - }); + should(actualData.length).equal(0) + should(dataEventCount).equal(0) + should(itemData.length).equal(0) + should(itemCount).equal(0) + done() + }) + xmlStream.pipe(parser) + }) - it("should be able to detect wrong resourcePath while parsing xml", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/manyItems.xml"); - const parser = new XmlParser({ resourcePath: "/wrong/noNodes", emitOnNodeName: true }); + it('should be able to detect wrong resourcePath while parsing xml', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/manyItems.xml') + const parser = new XmlParser({ resourcePath: '/wrong/noNodes', emitOnNodeName: true }) - let dataEventCount = 0; - let itemCount = 0; - parser.on("data", (data) => { - dataEventCount++; - }); + let dataEventCount = 0 + let itemCount = 0 + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("item", (data) => { - itemCount++; - }); + parser.on('item', (data) => { + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(0); - should(itemCount).equal(0); - done(); - }); - xmlStream.pipe(parser); - }); + should(dataEventCount).equal(0) + should(itemCount).equal(0) + done() + }) + xmlStream.pipe(parser) + }) - it("should properly parse a huge file.", (done) => { - const xmlStream = fs.createReadStream("./test/TestFiles/hugeFile.xml"); - const parser = new XmlParser({ resourcePath: "/wrong/path", emitOnNodeName: true }); + it('should properly parse a huge file.', (done) => { + const xmlStream = fs.createReadStream('./test/TestFiles/hugeFile.xml') + const parser = new XmlParser({ resourcePath: '/wrong/path', emitOnNodeName: true }) - let dataEventCount = 0; - let itemCount = 0; + let dataEventCount = 0 + let itemCount = 0 - parser.on("data", (data) => { - dataEventCount++; - }); + parser.on('data', (data) => { + dataEventCount++ + }) - parser.on("item", (item) => { - itemCount++; - }); + parser.on('item', (item) => { + itemCount++ + }) - parser.on("error", (err) => { - done(err); - }); + parser.on('error', (err) => { + done(err) + }) - parser.on("end", () => { + parser.on('end', () => { // console.log('dataEventCount=', dataEventCount) - should(dataEventCount).equal(0); - should(itemCount).equal(0); - done(); - }); - xmlStream.pipe(parser); - }); -}); + should(dataEventCount).equal(0) + should(itemCount).equal(0) + done() + }) + xmlStream.pipe(parser) + }) +})