如何获得一个NodeJS转换stream为每个input块发出多个logging?

我正在写一个转换stream,接受XML的传入stream,并发出一个JS对象的子集。

<item> <name>some name</name> <files> <file path='path/to/file'/> <file path='path/to//other/file'/> </files> </item> 

需要写两个项目对象

 { name: 'some name', file: 'path/to/file } 

 { name: 'some name', file: 'path/to/other/file } 

因为它将被传送到一个CSV作家。

代码看起来像

 import fs from 'fs' import expat from 'node-expat' import { Transform } from 'stream' const xParser = (filePath) => { const stream = fs.createReadStream(filePath) const parser = new expat.Parser('UTF-8') const tranny = Transform({ objectMode: true }) tranny._transform = function transform(data, encoding, done) { this.push(data) done() } let current let inItem = false let tag let attributes const startTag = (name, attrs) => { if (name === 'item') { inItem = true current = { name: '', files: [] } return } if (!inItem) return tag = name attributes = attrs if (tag === 'file') { current.files.push(attributes.path) } } const write = (file) => { tranny.write({ name: current.name, file }) } const endTag = (name) => { if (name === 'item') { // console.log('end item', JSON.stringify(current)) inItem = false if (current.files.length === 0) { write('') } else { current.files.forEach(file => { write(file) }) } tag = undefined attributes = undefined } } const handleText = (text) => { if (!inItem) return if (tag === 'name') { current.name = current.name.concat(text).trim() } } const handleDone = () => { console.log('done') tranny.end() } parser .on('startElement', startTag) .on('endElement', endTag) .on('text', handleText) .on('end', handleDone) stream.pipe(parser) return tranny } module.exports = xParser 

当xml是简单的

 <item> <name>some name</name> <files> <file path='path/to/file'/> </files> </item> 

这工作正常,但是当它击中一个item与多个领域只是停止和'end'触发第二tranny.write发生。

我如何获得转换stream为每个input块输出多个logging?

好的修好了

这个解决scheme不是做多个tranny.write而是在tranny._transform函数中进行数据转换( tranny._transform应该是显而易见的)。

如此

 tranny._transform = function transform(data, encoding, done) { if (data.files.length > 0) { data.files.forEach((file) => { this.push({ name: data.name, file }) }) } else { this.push({ name: data.name, file: '' }) } done() } 

endTag处理程序现在看起来像

 const endTag = (name) => { if (name === 'item') { inItem = false tranny.write(current) tag = undefined attributes = undefined } } 

这意味着我也可以删除writefunction。

现在它工作,并validation当我这样做

 import xParser from './xParser' import concat from 'concat-stream' xmlParser('data/mybigdatafile.xml') .pipe(concat((data) => { console.log(JSON.stringify(data)); })) 

这为我吐出了全套的数据。