将xml输入到sax Parser,如何打印xml流?

时间:2011-10-04 10:47:08

标签: java android sockets stream saxparser

我正在尝试通过套接字连接到一个远程服务器,我从套接字返回大的xml响应,由'\ n'字符分隔。

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

我正在尝试使用SAX Parser解析这些xml。理想情况下,我希望通过搜索'\ n'来获得对字符串的完整响应,并将此响应提供给解析器。但是因为我的单个响应非常大,所以当在字符串中保存如此大的xml时,我得到outOfMemory Exception。因此唯一的选择是将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. 在xml解析中是否存在上述给定错误的其他原因 除了编码问题
  2. 有没有办法打印(或写入任何文件)SAX的输入为 它来自socket?
  3. 在尝试了Hemal Pandya的答案之后......

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

    我挂载SD卡时创建了一个名为log.txt的新文件,但它是空的......我用这个吗?

    最后我是怎么做的..

    我用TeeInputStream本身进行了解决。感谢Hemal Pandya建议......

    //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();
    }
    

2 个答案:

答案 0 :(得分: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语义,虽然查看文档和你的要求看起来你想要在结束时单独关闭它

答案 1 :(得分:0)

我对Expat并不熟悉,但为了实现您的目的,一般来说,您需要一个SAX解析器,它支持将数据推送到解析器,而不是让解析器从源中提取数据。检查Expat是否支持推送模型。如果是这样,那么你可以简单地从套接字中读取一大块数据,将其推送到解析器,它将从chuck中解析任何数据,缓存剩余的数据以便在下一次推送时使用。根据需要重复,直到准备好关闭套接字连接。在此模型中,\n分隔符将被视为节点之间的杂项空格,因此您必须使用SAX事件来检测新<Response>节点何时打开和关闭。此外,因为您在数据中接收多个<Response>节点,并且XML不允许超过1个顶级文档节点,所以在开始推送套接字之前,需要将自定义开始标记推送到解析器中数据进入解析器。然后,自定义开始标记将成为顶级文档节点,<Response>节点将成为它的子节点。