Tools for learning Japanese.
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

51 righe
1.9 KiB

  1. import { Transform, TransformCallback } from 'stream';
  2. import { xml2json } from 'xml-js';
  3. export interface XmlToJsonLinesTransformStreamOptions {
  4. entryTagName: string;
  5. }
  6. class XmlToJsonLinesTransformStream extends Transform {
  7. private charactersToParse?: string;
  8. constructor(private readonly options: XmlToJsonLinesTransformStreamOptions) {
  9. super();
  10. // noop
  11. }
  12. // eslint-disable-next-line no-underscore-dangle
  13. _transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback) {
  14. const chunkStr = chunk.toString('utf-8');
  15. if (typeof this.charactersToParse !== 'string') {
  16. const firstEntryIndex = chunkStr.indexOf(`<${this.options.entryTagName}>`);
  17. this.charactersToParse = chunkStr.slice(firstEntryIndex);
  18. } else {
  19. this.charactersToParse += chunkStr;
  20. }
  21. let theCharacters = `${this.charactersToParse}`;
  22. let nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`);
  23. let nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`);
  24. do {
  25. const xml = theCharacters
  26. .slice(
  27. nextOpenTagIndex,
  28. nextCloseTagIndex + this.options.entryTagName.length + 3,
  29. )
  30. .replace(/&(.+?);/g, '$1'); // FIXME better handling of XML entities??? This makes the pipe hang for some reason
  31. const json = xml2json(xml, { compact: true });
  32. this.push(`${json}\n`);
  33. theCharacters = theCharacters.slice(nextCloseTagIndex + this.options.entryTagName.length + 3);
  34. nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`);
  35. nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`);
  36. } while (nextOpenTagIndex !== -1 && nextCloseTagIndex !== -1);
  37. this.charactersToParse = theCharacters;
  38. callback(null, '');
  39. }
  40. }
  41. export const createXmlToJsonLines = (options = {
  42. entryTagName: 'entry',
  43. } as XmlToJsonLinesTransformStreamOptions) => new XmlToJsonLinesTransformStream(options);