2011-10-04 40 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>节点将成为它的子节点。