2015-11-13 22 views
0

我正在通過Node中的NET套接字接收XML/SOAP。較大的SOAP響應被分塊,因此在將它傳遞給XML解析器之前,我需要連接SOAP信封。Node.js NET連接分塊XML數據

這裏是企圖到目前爲止

//client.net.setEncoding('utf8'); 
var data = ''; 
client.net.on('data', function(response) { 
    var read = response.toString(); 
    console.log("READING == "+read); 
    if (read.substr(read.length-15) === "</env:Envelope>") { 
     if(data.length > 0) { 
      /* soap envelope is finally complete, pass to xml parser */ 
      parser.parseString(data += response); 
      data = ''; 
     } 
     /* soap envelope is complete, pass to xml parser */ 
     parser.parseString(response); 
    } else { 
     /* not soap response */ 
     if (read.substr(0, 4) === "HTTP") return; 
     /* add chunck to data */ 
     data += response; 
    } 
}); 

傳入的數據看起來像(這是小的反應)

READING == HTTP/1.1 200 OK 
Content-Type:application/soap+xml; charset="utf-8" 
Content-Length:644 


READING == <?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header><n:Response x 
mlns:n="http://www.example.com/" env:role="http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver" env:mustUnderst 
and="true">SetTrackingFrequency</n:Response></env:Header><env:Body><n:ResponseSetTrackingFrequency xmlns:n="http://www.example.com/ipr 
s/gps/soap"><n:Status>none</n:Status><n:ApplicationID>18</n:ApplicationID><n:RequestID>0</n:RequestID><n:FrequencySecs>0</n:FrequencySecs><n 
:ExpirationSecs>0</n:ExpirationSecs></n:ResponseSetTrackingFrequency></env:Body></env:Envelope> 

當包膜不完整,我正在合併塊。

除了解析器開始拋出錯誤之外,這看起來接近工作。

error: uncaughtException: Text data outside of root node. 

編輯 - 進一步信息

此代碼提供了錯誤,但經過相同的反應?

client.net.on('data', function(response) { 
    var read = response.toString(); 
    if (read.substr(read.length-15) === "</env:Envelope>") { 
     parser.parseString(response); 
     return; 
    } 
} 

此代碼沒有給出錯誤

client.net.on('data', function(response) { 
     parser.parseString(response); 
     return; 
} 

完整的錯誤:

2015-11-13T19:34:50.355Z - error: uncaughtException: Text data outside of root node. 
Line: 0 
Column: 1228 
Char: H date=Fri Nov 13 2015 19:34:50 GMT+0000 (GMT Standard Time), pid=25712, uid=null, gid=null, cwd=C:\Users\v_lowe\Dropbox\nodejs\v4 -of 
, execPath=C:\Program Files\nodejs\node.exe, version=v4.1.1, argv=[C:\Program Files\nodejs\node.exe, C:\Users\v_lowe\Dropbox\nodejs\v4 -of\i 
ndex.js], rss=44589056, heapTotal=34005760, heapUsed=21471184, loadavg=[0, 0, 0], uptime=954829.8959002, trace=[column=10, file=-of\node_mod 
ules\xml2js\node_modules\sax\lib\sax.js, function=error (C:\Users\v_lowe\Dropbox\nodejs\v4, line=666, method=null, native=false, column=7, f 
ile=-of\node_modules\xml2js\node_modules\sax\lib\sax.js, function=strictFail (C:\Users\v_lowe\Dropbox\nodejs\v4, line=692, method=null, nati 
ve=false, column=15, file=-of\node_modules\xml2js\node_modules\sax\lib\sax.js, function=Object.write (C:\Users\v_lowe\Dropbox\nodejs\v4, lin 
e=1035, method=write (C:\Users\v_lowe\Dropbox\nodejs\v4, native=false, column=31, file=-of\node_modules\xml2js\lib\xml2js.js, function=Parse 
r.exports.Parser.Parser.parseString (C:\Users\v_lowe\Dropbox\nodejs\v4, line=497, method=exports.Parser.Parser.parseString (C:\Users\v_lowe\ 
Dropbox\nodejs\v4, native=false, column=59, file=-of\node_modules\xml2js\lib\xml2js.js, function=Parser.parseString (C:\Users\v_lowe\Dropbox 
\nodejs\v4, line=7, method=parseString (C:\Users\v_lowe\Dropbox\nodejs\v4, native=false, column=12, file=-of\lib\gps_parse.js, function=Sock 
et.<anonymous> (C:\Users\v_lowe\Dropbox\nodejs\v4, line=41, method=<anonymous> (C:\Users\v_lowe\Dropbox\nodejs\v4, native=false, column=13, 
file=events.js, function=emitOne, line=77, method=null, native=false, column=7, file=events.js, function=Socket.emit, line=169, method=emit, 
native=false, column=16, file=_stream_readable.js, function=readableAddChunk, line=146, method=null, native=false, column=10, file=_stream_ 
readable.js, function=Socket.Readable.push, line=110, method=Readable.push, native=false], stack=[Error: Text data outside of root node., Li 
ne: 0, Column: 1228, Char: H,  at error (C:\Users\v_lowe\Dropbox\nodejs\v4 -of\node_modules\xml2js\node_modules\sax\lib\sax.js:666:10), 
    at strictFail (C:\Users\v_lowe\Dropbox\nodejs\v4 -of\node_modules\xml2js\node_modules\sax\lib\sax.js:692:7),  at Object.write (C:\User 
s\v_lowe\Dropbox\nodejs\v4 -of\node_modules\xml2js\node_modules\sax\lib\sax.js:1035:15),  at Parser.exports.Parser.Parser.parseString (C: 
\Users\v_lowe\Dropbox\nodejs\v4 -of\node_modules\xml2js\lib\xml2js.js:497:31),  at Parser.parseString (C:\Users\v_lowe\Dropbox\nodejs\v4 
-of\node_modules\xml2js\lib\xml2js.js:7:59),  at Socket.<anonymous> (C:\Users\v_lowe\Dropbox\nodejs\v4 -of\lib\gps_parse.js:41:12),  a 
t emitOne (events.js:77:13),  at Socket.emit (events.js:169:7),  at readableAddChunk (_stream_readable.js:146:16),  at Socket.Reada 
ble.push (_stream_readable.js:110:10)] 

回答

0

一種方式來做到這一點是通過尋找結束模式,而不是使用之初,基本上是:

  • 每次被接收到的時間累積的數據在緩衝器中
  • 每次數據被追加到緩衝,在更新後的緩衝器檢查結束模式
  • 只要結束模式在緩衝區中發現:
    • 從開始到第一個結束模式切分段,這是您的框架!
    • 繼續並解析/處理該幀。一定要從緩衝區中刪除它。
    • 繼續砍緩衝區,如果它仍包含結束模式,否則讓它成長

這一切!

var textBuffer = ''; 
var parseFrame = function (str){}; 

function processChunk (chunk) { 
    var segments, frame; 
    var startChar = String.fromCharCode(1); 
    var endChar = String.fromCharCode(0); 

    // having no endChar will skip the loop, 
    // but we still save the chunk 
    textBuffer += chunk; 

    while (textBuffer && textBuffer.indexOf(endChar) !== -1) { 
    // use endChar in lieu of startChar so we don’t 
    // miss a chunk without beginning 
    segments = textBuffer.split(endChar); 

    // first chunk we extract may or may not have a startChar 
    // replace() will have no effect if startChar is absent 
    frame = segments.shift().replace(startChar, ''); 

    // if join() results in '', endChar won’t be found, 
    // and we will get out of loop 
    textBuffer = segments.join(endChar); 

    // beware: it is possible that the frame 
    // is incomplete if we *never* got the startChar, 
    // the next chunks will be OK though 
    try { parseFrame(frame); } 
    catch (err) { console.log(err); } 
    } 
}