最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Node.js streams for XML transformations with xml-stream - Stack Overflow

programmeradmin1浏览0评论

I'm using xml-stream to read a large XML file. 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

Here is xml-stream snippet collecting required elements:

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

How do I build streams for step 1 and 2?

P.S. xml-stream has only console.log examples

UPDATE 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.

I'm using xml-stream to read a large XML file. 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

Here is xml-stream snippet collecting required elements:

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

How do I build streams for step 1 and 2?

P.S. xml-stream has only console.log examples

UPDATE 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.

Share Improve this question edited Jun 18, 2015 at 13:09 krl asked Jun 18, 2015 at 9:28 krlkrl 5,2964 gold badges40 silver badges54 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

Mission acplished. The function below returns transform stream that can be piped to any writable stream. liner._flush is necessary only you want to add some data in the end of the stream.

P.S. A handy module (not used here) https://github./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.

At the end, you have stream, which you can use according to 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.

I remend node-modules. and libraries.io/npm to improve the NPM search.

发布评论

评论列表(0)

  1. 暂无评论