Javascript NodeJS解析流,定义块的起点和终点
被节点的文件系统解析弄糊涂了。这是我的密码:Javascript NodeJS解析流,定义块的起点和终点,javascript,xml,node.js,node.js-stream,Javascript,Xml,Node.js,Node.js Stream,被节点的文件系统解析弄糊涂了。这是我的密码: var fs = require('fs'), xml2js = require('xml2js'); var parser = new xml2js.Parser(); var stream = fs.createReadStream('xml/bigXML.xml'); stream.setEncoding('utf8'); stream.on('data', function(chunk){ parser.parseS
var fs = require('fs'),
xml2js = require('xml2js');
var parser = new xml2js.Parser();
var stream = fs.createReadStream('xml/bigXML.xml');
stream.setEncoding('utf8');
stream.on('data', function(chunk){
parser.parseString(chunk, function (err, result) {
console.dir(result);
console.log('Done');
});
});
stream.on('end', function(chunk){
// file have been read over,do something...
console.log("IT'S OVER")
});
这导致……什么也不会发生。XML2JS/解析器根本没有输出。当我尝试console.log(chunk)
时,似乎除了字节大小之外,chunk
没有以任何类型的有意义的chunk输出。一个“块”的输出为:
<?xml version="1.0" encoding="UTF-8"?>
<merchandiser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="merchandiser.xsd">
<header><merchantId>1237</merchantId><merchantName>NORDSTROM.com</merchantName><createdOn>12/13/2013 23:50:57</createdOn></header>
<product product_id="52863929">// product info</product>
<product product_id="26537849">// product info</product>
<product product_id="25535647">// product info</product>
xml2js用于完全加载的xml 在使用sax的情况下,它是一个流解析器: //安装
npm install sax
//此代码用于打印所有产品标识
var fs = require('fs');
var sax = require('sax');
var saxStream = sax.createStream();
saxStream.onopentag = function (node) {
if(node.name === 'PRODUCT'){
console.log(node.attributes.PRODUCT_ID);
}
};
fs.createReadStream('xml/bigXML.xml').pipe(saxStream);
输出:
52863929
26537849
25535647
你有两种可能来解决你的问题 如damphat所述,XML2JS需要完整的XML内容才能解析数据。但是您有一个文件流,它可以一块一块地流数据。第一种解决方案是将此数据流转换成一个漂亮的大缓冲区,然后将其发送到XML2JS。为此,您可以使用(
npm i stream to
)将文件流转换为一个缓冲区数组,然后我们将使用以下方法将其连接为一个缓冲区:
var fs = require('fs')
var streamTo = require('stream-to')
var xml2js = require('xml2js')
var file = fs.createReadStream('input.xml')
streamTo.array(file, function (err, arr) {
if (err) return console.log(err.message)
var content = Buffer.concat(arr)
var parser = new xml2js.Parser()
parser.parseString(content, function (err, res) {
if (err) return console.log(err.message)
console.log(res.merchandiser.product)
})
})
这工作得很好,但是因为它需要将完整的文件保存到内存中,所以如果您的输入文件太大,它将无法工作。要处理非常大的文件,需要使用流式XML解析器,例如sax
。但是,sax
不创建Javascript对象,而是一个EventEmitter,使用起来有点困难,因为您必须处理所有相关事件来动态构建对象
您可以使用实例,它支持XPath语法的一小部分。该库每次匹配XPath模式时都会发出一个match
事件。下面是一个例子:
var saxpath = require('saxpath')
var fs = require('fs')
var sax = require('sax')
var saxParser = sax.createStream(true)
var streamer = new saxpath.SaXPath(saxParser, '/merchandiser/product')
streamer.on('match', function(xml) {
console.log(xml);
});
fs.createReadStream('input.xml').pipe(saxParser)
然后您有两个选项:
xml2js
一次解析单个产品此操作已结束-请参见编辑以了解
节点中包含的内容的示例。使用XML2JS(仅使用fs
和parseString
),我对结果执行for
循环,并将对象转换为JSON,以获取其中的所有信息。在这里使用Sax可能吗?onopentag
似乎只提供了一点细节,而不是
本身的内容。好帖子。问题是这两种解决方案对我都不起作用。该文件为1.5gb,因此缓冲区解决方案无法工作。我需要创建javascript对象,因此根据您的帖子sax
也不起作用。那么…我能在这里做什么?!我找不到方法让Node加载1.5gb文件,我在尝试时遇到缓冲区错误。好吧,那么缓冲区就不可能了。我编辑了我的答案,使用SaXPath为您提供了几个选项。需要明确的是:sax将起作用。我只是需要您做更多的工作来从sax事件重新创建javascript对象。但它会工作得很好!您编辑的示例运行良好,非常感谢您的详细解释,这个问题在Stack/Google上的其他任何地方都没有很好的答案,所以希望它能对其他人有所帮助。我在这里发布的后续内容可能会对你有所帮助,因为Sax拒绝在数据中包含CDATA
:
var saxpath = require('saxpath')
var fs = require('fs')
var sax = require('sax')
var saxParser = sax.createStream(true)
var streamer = new saxpath.SaXPath(saxParser, '/merchandiser/product')
streamer.on('match', function(xml) {
console.log(xml);
});
fs.createReadStream('input.xml').pipe(saxParser)