2011-10-04 53 views
2

嗯,我試圖通過套接字連接到一個遠程服務器,並從套接字返回大的XML響應,由'\ n'字符分隔。流xml輸入到薩克斯解析器,如何打印xml流?

<?xml version="1.0" encoding="UTF-8"?> 
<Response> 
    <data> 
     ....... 
     ....... 
    </data> 
</Response>\n <---- \n acts as delimiter 
<?xml version="1.0" encoding="UTF-8"?> 
<Response> 
    <data> 
     .... 
     .... 
    </data> 
</Response>\n 
.. 

我想解析這些XML使用SAX解析器。理想情況下,我希望通過搜索'\ n'來獲得對字符串的完整響應,並將此響應提供給解析器。但是因爲我的單個響應非常大,所以當我在字符串中保存如此大的xml時,我將獲得OutOfMemory異常。因此唯一的選擇是將xml傳輸到SAX。

SAXParserFactory spfactory = SAXParserFactory.newInstance(); 
SAXParser saxParser = spfactory.newSAXParser(); 
XMLReader xmlReader = saxParser.getXMLReader(); 

xmlReader.setContentHandler(new MyDefaultHandler(context)); 

InputSource xmlInputSource = new InputSource(new  
        CloseShieldInputStream(mySocket.getInputStream())); 
xmlReader.parse(xmlInputSource); 

我正在使用closeShieldInputStream來防止SAX由於'\ n'而關閉異常套接字流。我問上一個previous question ..

現在有時我得到解析錯誤

org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 8: not well-formed (invalid token) 

我搜索了它,並found了這個錯誤通常正值當實際的XML編碼是不一樣的東西SAX期待。我寫了一個C程序並打印出xml,我所有的xml都是用UTF-8編碼的。

現在我的問題..

  1. 是否有任何其他原因解析 除了編碼問題
  2. 在XML上面給出的錯誤有沒有辦法打印(或寫入任何文件)的輸入到SAX作爲 它從套接字流?

試圖血管潘迪亞的回答後..

OutputStream log = new BufferedOutputStream(new FileOutputStream("log.txt")); 
InputSource xmlInputSource = new InputSource(new CloseShieldInputStream(new 
            TeeInputStream(mReadStream, log))); 
xmlReader.parse(xmlInputSource); 

的log.txt得到它empty..Am我使用這一權利創造了名的新文件,當我安裝SD卡,但?

那麼最後我是怎麼做到的..

我TeeInputStream工作了itself..thanks血管潘迪亞的提示..

//open a log file in append mode.. 
OutputStream log = new BufferedOutputStream(new FileOutputStream("log.txt",true)); 
InputSource xmlInputSource = new InputSource(new CloseShieldInputStream(new 
             TeeInputStream(mReadStream, log))); 
try{ 
    xmlReader.parse(xmlInputSource); 
    //flush content in the log stream to file..this code only executes if parsing completed successfully 
    log.flush(); 
}catch(SaxException e){ 
    //we want to get the log even if parsing failed..So we are making sure we get the log in either case.. 
    log.flush(); 
} 
+0

請參閱我的編輯,我已經爲每個響應添加了一個doctype元素。是否是第一個錯誤的原因? – Krishnabhadra

+0

不是在'try'和'catch'塊中都調用'log.flush()',而是另外一個選項是這樣做:嘗試xmlReader.parse(xmlInputSource); } catch(SaxException e){*} log exception */ } log.flush(); ' –

+0

hmmm ...但在我的情況下,當我有一個異常,我從異常捕獲本身返回正確的..所以這是不可能在我的情況下 – Krishnabhadra

回答

1

有沒有辦法打印(或寫入任何文件)輸入到SAX作爲 它從套接字流?

Apache Commons有一個TeeInputStream應該是有用的。

OutputStream log = new BufferedOutputStream(new FileOutputtStream("response.xml")); 
InputSource xmlInputSource = new InputSource(new  
        CloseShieldInputStream(new TeeInputStream(mySocket.getInputStream(), log))); 

我沒有用它,你可能想先嚐試在一個獨立的程序,找出close語義,雖然看文檔和您的要求,它看起來像你想結束處分別關閉。

+0

感謝您的迴應..可以看到編輯我的問題 – Krishnabhadra

+0

正如我所說我沒有嘗試過,你應該嘗試在一個小的獨立程序,例如,而不是使用'socket.getInputStream()'使用'FileInputStream',而不是使用創建一個'InputSource'它只是打印在控制檯上。但是......你最後調用'close()'嗎?這可能是它沒有得到任何東西(其緩衝)的原因。 –

0

我對Expat並不熟悉,但要實現您正在描述的一般情況,您需要一個SAX解析器,它支持將數據推送到解析器而不是讓解析器從源中提取數據。檢查Expat是否支持推送模式。如果是這樣,那麼您可以簡單地從套接字中讀取一段數據,將其推送到解析器,然後它將解析來自卡盤的所有數據,緩存任何剩餘數據以供下次推送時使用。根據需要重複,直到準備好關閉套接字連接。在此模型中,\n分隔符將被視爲節點之間的雜項空白,因此您必須使用SAX事件來檢測新節點何時打開和關閉。另外,因爲您在數據中接收到多個<Response>節點,並且XML不允許多個頂級文檔節點,所以在您開始將套接字數據推送到解析器之前,您需要將自定義開啓標記推入解析器中。自定義開始標記將成爲頂級文檔節點,並且<Response>節點將成爲它的子節點。