Tools for learning Japanese.
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

52 linhas
2.0 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. try {
  15. const chunkStr = chunk.toString('utf-8');
  16. if (typeof this.charactersToParse !== 'string') {
  17. const firstEntryIndex = chunkStr.indexOf(`<${this.options.entryTagName}>`);
  18. this.charactersToParse = chunkStr.slice(firstEntryIndex);
  19. } else {
  20. this.charactersToParse += chunkStr;
  21. }
  22. let theCharacters = `${this.charactersToParse}`;
  23. let nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`);
  24. let nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`);
  25. const closeTagLength = this.options.entryTagName.length + 3;
  26. do {
  27. const xml = theCharacters
  28. .slice(nextOpenTagIndex, nextCloseTagIndex + closeTagLength)
  29. .replace(/&(.+?);/g, '$1'); // FIXME better handling of XML entities??? This makes the pipe hang for some reason
  30. const json = xml2json(xml, { compact: true });
  31. this.push(`${json}\n`);
  32. theCharacters = theCharacters.slice(nextCloseTagIndex + closeTagLength);
  33. nextOpenTagIndex = theCharacters.indexOf(`<${this.options.entryTagName}>`);
  34. nextCloseTagIndex = theCharacters.indexOf(`</${this.options.entryTagName}>`);
  35. } while (nextOpenTagIndex !== -1 && nextCloseTagIndex !== -1);
  36. this.charactersToParse = theCharacters;
  37. callback(null, '');
  38. } catch (err) {
  39. callback(err as Error);
  40. }
  41. }
  42. }
  43. export const createXmlToJsonLines = (options = {
  44. entryTagName: 'entry',
  45. } as XmlToJsonLinesTransformStreamOptions) => new XmlToJsonLinesTransformStream(options);