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