简体   繁体   English

Node.js使用xml-stream进行XML转换

[英]Node.js streams for XML transformations with xml-stream

I'm using xml-stream to read a large XML file. 我正在使用xml-stream来读取大型XML文件。 I'd like to: 我想:

  1. pipe collected elements to a stream 将收集的元素管道传输到流中
  2. optionally, to transform those elements using one or more pipes 可选地,使用一个或多个管道来转换这些元素
  3. pipe the result to an http response 将结果传递给http响应

Here is xml-stream snippet collecting required elements: 以下是收集所需元素的xml-stream片段:

xml.on('endElement: item', function(item) {
  // pipe item to stream
})

How do I build streams for step 1 and 2? 如何为第1步和第2步构建流?

PS xml-stream has only console.log examples PS xml-stream只有console.log示例

UPDATE 1 更新1

Here is what I wrote so far: 这是我到目前为止写的:

stream = require('stream');

let liner = new stream.Transform( { objectMode: true } );

liner._transform = function (data, encoding, done) {
  this.push(data);
  console.log(data);
  console.log('======================='); 
  done();
};

let fileStream = fs.createReadStream(fileNames[0]);

let xmlStream = new XmlStream(fileStream);

let counter = 0;

xmlStream.on('endElement: Item', function(el) {
  liner.write(el);
  counter += 1;
});

xmlStream.on('end', function() {
  console.log(counter);
  liner.end();
});

_transform get called on every write , however piping liner stream to http result doesn't produce any output. 每次write都会调用_transform ,但是到http结果的管道liner流不会产生任何输出。

Mission accomplished. 任务完成。 The function below returns transform stream that can be piped to any writable stream. 下面的函数返回transform stream ,可以通过管道输送到任何写流。 liner._flush is necessary only you want to add some data in the end of the stream. 只有你想在流的末尾添加一些数据才需要liner._flush

PS A handy module (not used here) https://github.com/rvagg/through2 PS一个方便的模块(这里没有使用) https://github.com/rvagg/through2

const fs = require('fs');
const stream = require('stream');
const XmlStream = require('xml-stream');

function getTransformStream() { 

  let liner = new stream.Transform( { objectMode: true } );

  liner._transform = function (data, encoding, done) {
    // have your transforms here
    this.push(data);
    console.log(data);
    console.log('=======================');
    done();
  };

  liner._flush = function (done) {
    console.log('DONE DONE DONE DONE');
    done();
  };


  let fileStream = fs.createReadStream('filename');

  let xmlStream = new XmlStream(fileStream);

  let counter = 0;

  xmlStream.on('endElement: Item', function(el) {
    liner.write(JSON.stringify(el));
    counter += 1;
  });

  xmlStream.on('end', function() {
    console.log(counter);
    liner.end();
  });

  return liner;
}

Maybe you should check the example, that the library provides. 也许您应该查看该库提供的示例。 If you have done that, it would be nice if you have pointed that out. 如果你已经这样做了,如果你已经指出了它会很好。 So I use Promised land for data flow and Highlandjs to create a stream from array, which has only one element- the item . 所以我使用的数据流量和Highlandjs应许之地,以创建阵列流,它只有一个元素-该item

At the end, you have stream, which you can use according to Highland docs. 最后,您有流,您可以根据Highland docs使用。

    var Land = require('promised-land')
    var stream = fs.createReadStream(path.join(__dirname, 'file.xml'));
    var xml = new XmlStream(stream);
    xml.preserve('item', true);
    xml.collect('subitem');
    var arr = []
    xml.on('endElement: item', function(item) {
    arr.push(item)
    });
    xml.on('end', function(data) {
        var highlandStream = _(data)
        Land.emit('endStream', highlandStream)
    });
    Land.promise('endStream').then(function(stream) {
    // now you can pipe your stream
    })

Still, it is possible much more simpler and smarter solution if you use some of the alternative Node.js libraries for reading XML files. 尽管如此,如果您使用一些备用Node.js库来读取XML文件,它可能会更简单,更智能。

I recommend node-modules.com and libraries.io/npm to improve the NPM search. 我建议使用node-modules.com和libraries.io/npm来改进NPM搜索。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM