|
@@ -8,9 +8,14 @@ export interface XmlToJsonLinesTransformStreamOptions { |
|
|
class XmlToJsonLinesTransformStream extends Transform { |
|
|
class XmlToJsonLinesTransformStream extends Transform { |
|
|
private charactersToParse?: string; |
|
|
private charactersToParse?: string; |
|
|
|
|
|
|
|
|
constructor(private readonly options: XmlToJsonLinesTransformStreamOptions) { |
|
|
|
|
|
|
|
|
private readonly openTag: string; |
|
|
|
|
|
|
|
|
|
|
|
private readonly closeTag: string; |
|
|
|
|
|
|
|
|
|
|
|
constructor(options: XmlToJsonLinesTransformStreamOptions) { |
|
|
super(); |
|
|
super(); |
|
|
// noop |
|
|
|
|
|
|
|
|
this.openTag = `<${options.entryTagName}>`; |
|
|
|
|
|
this.closeTag = `</${options.entryTagName}>`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-underscore-dangle |
|
|
// eslint-disable-next-line no-underscore-dangle |
|
@@ -18,26 +23,29 @@ class XmlToJsonLinesTransformStream extends Transform { |
|
|
try { |
|
|
try { |
|
|
const chunkStr = chunk.toString('utf-8'); |
|
|
const chunkStr = chunk.toString('utf-8'); |
|
|
if (typeof this.charactersToParse !== 'string') { |
|
|
if (typeof this.charactersToParse !== 'string') { |
|
|
const firstEntryIndex = chunkStr.indexOf(`<${this.options.entryTagName}>`); |
|
|
|
|
|
|
|
|
const firstEntryIndex = chunkStr.indexOf(this.openTag); |
|
|
this.charactersToParse = chunkStr.slice(firstEntryIndex); |
|
|
this.charactersToParse = chunkStr.slice(firstEntryIndex); |
|
|
} else { |
|
|
} else { |
|
|
this.charactersToParse += chunkStr; |
|
|
this.charactersToParse += chunkStr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let theCharacters = `${this.charactersToParse}`; |
|
|
let theCharacters = `${this.charactersToParse}`; |
|
|
let nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`); |
|
|
|
|
|
let nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`); |
|
|
|
|
|
const closeTagLength = this.options.entryTagName.length + 3; |
|
|
|
|
|
|
|
|
let nextOpenTagIndex = theCharacters.indexOf(this.openTag); |
|
|
|
|
|
let nextCloseTagIndex = theCharacters.indexOf(this.closeTag); |
|
|
|
|
|
let sliceEnd = nextCloseTagIndex + this.closeTag.length; |
|
|
do { |
|
|
do { |
|
|
const xml = theCharacters |
|
|
|
|
|
.slice(nextOpenTagIndex, nextCloseTagIndex + closeTagLength) |
|
|
|
|
|
.replace(/&(.+?);/g, '$1'); // FIXME better handling of XML entities??? This makes the pipe hang for some reason |
|
|
|
|
|
const json = xml2json(xml, { compact: true }); |
|
|
|
|
|
this.push(`${json}\n`); |
|
|
|
|
|
theCharacters = theCharacters.slice(nextCloseTagIndex + closeTagLength); |
|
|
|
|
|
nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`); |
|
|
|
|
|
nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`); |
|
|
|
|
|
} while (nextOpenTagIndex !== -1 && nextCloseTagIndex !== -1); |
|
|
|
|
|
|
|
|
if (nextOpenTagIndex > -1 && nextCloseTagIndex > -1) { |
|
|
|
|
|
const xml = theCharacters |
|
|
|
|
|
.slice(nextOpenTagIndex, sliceEnd) |
|
|
|
|
|
.replace(/&(.+?);/g, '$1'); // FIXME better handling of XML entities??? This makes the pipe hang for some reason |
|
|
|
|
|
const json = xml2json(xml, { compact: true }); |
|
|
|
|
|
this.push(`${json}\n`); |
|
|
|
|
|
theCharacters = theCharacters.slice(sliceEnd); |
|
|
|
|
|
} |
|
|
|
|
|
nextOpenTagIndex = theCharacters.indexOf(this.openTag); |
|
|
|
|
|
nextCloseTagIndex = theCharacters.indexOf(this.closeTag); |
|
|
|
|
|
sliceEnd = nextCloseTagIndex + this.closeTag.length; |
|
|
|
|
|
} while (nextOpenTagIndex > -1 && nextCloseTagIndex > -1); |
|
|
this.charactersToParse = theCharacters; |
|
|
this.charactersToParse = theCharacters; |
|
|
callback(null, ''); |
|
|
callback(null, ''); |
|
|
} catch (err) { |
|
|
} catch (err) { |
|
|