Files
dbgate/plugins/dbgate-plugin-xml/src/backend/reader.js
2023-01-21 17:49:16 +01:00

71 lines
2.0 KiB
JavaScript

const fs = require('fs');
const stream = require('stream');
const NodeXmlStream = require('node-xml-stream-parser');
const { getLogger } = global.DBGATE_TOOLS;
const logger = getLogger('xmlReader');
class ParseStream extends stream.Transform {
constructor({ itemElementName }) {
super({ objectMode: true });
let element = itemElementName;
this.push({
__isStreamHeader: true,
__isDynamicStructure: true,
});
this.rowsWritten = 0;
this.parser = new NodeXmlStream();
this.stack = [];
this.parser.on('opentag', (name, attrs) => {
if (!element && this.stack.length == 1) {
element = name;
}
this.stack.push({ name, attrs, nodes: {} });
});
this.parser.on('text', (text) => {
if (this.stack.length >= 2) {
this.stack[this.stack.length - 2].nodes[this.stack[this.stack.length - 1].name] = text;
}
if (this.stack.length >= 1) {
this.stack[this.stack.length - 1].nodes.$text = text;
}
});
this.parser.on('cdata', (text) => {
if (this.stack.length >= 2) {
this.stack[this.stack.length - 2].nodes[this.stack[this.stack.length - 1].name] = text;
}
if (this.stack.length >= 1) {
this.stack[this.stack.length - 1].nodes.$text = text;
}
});
this.parser.on('closetag', (name, attrs) => {
if (name == element) {
const obj = { ...this.stack[this.stack.length - 1].attrs, ...this.stack[this.stack.length - 1].nodes };
if (Object.keys(obj).length > 0) {
this.rowsWritten += 1;
this.push(obj);
}
}
this.stack.splice(-1);
});
}
_transform(chunk, encoding, done) {
this.parser.write(chunk);
done();
}
}
async function reader({ fileName, encoding = 'utf-8', itemElementName }) {
logger.info(`Reading file ${fileName}`);
const fileStream = fs.createReadStream(fileName, encoding);
const parser = new ParseStream({ itemElementName });
fileStream.pipe(parser);
return parser;
}
module.exports = reader;