Browse Source

Add failsafe for stream parsers

Ensure both open and close tags have been read.
master
TheoryOfNekomata 1 year ago
parent
commit
d81fc04c68
1 changed files with 23 additions and 15 deletions
  1. +23
    -15
      src/streams.ts

+ 23
- 15
src/streams.ts View File

@@ -8,9 +8,14 @@ export interface XmlToJsonLinesTransformStreamOptions {
class XmlToJsonLinesTransformStream extends Transform {
private charactersToParse?: string;

constructor(private readonly options: XmlToJsonLinesTransformStreamOptions) {
private readonly openTag: string;

private readonly closeTag: string;

constructor(options: XmlToJsonLinesTransformStreamOptions) {
super();
// noop
this.openTag = `<${options.entryTagName}>`;
this.closeTag = `</${options.entryTagName}>`;
}

// eslint-disable-next-line no-underscore-dangle
@@ -18,26 +23,29 @@ class XmlToJsonLinesTransformStream extends Transform {
try {
const chunkStr = chunk.toString('utf-8');
if (typeof this.charactersToParse !== 'string') {
const firstEntryIndex = chunkStr.indexOf(`<${this.options.entryTagName}>`);
const firstEntryIndex = chunkStr.indexOf(this.openTag);
this.charactersToParse = chunkStr.slice(firstEntryIndex);
} else {
this.charactersToParse += chunkStr;
}

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 {
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;
callback(null, '');
} catch (err) {


Loading…
Cancel
Save