SAX events not fired when they could be
---------------------------------------

         Key: XERCESC-1607
         URL: http://issues.apache.org/jira/browse/XERCESC-1607
     Project: Xerces-C++
        Type: Bug

  Components: SAX/SAX2  
    Versions: 2.5.0, 2.7.0    
 Environment: Solaris 2.8, 2.10 SPARC - Sun Studio 11
    Reporter: Gary Hughes


If a BinInputStream returns a valid fragment of XML that should generate SAX 
parse events it does not necessarily do so before called readBytes again, if 
the BinInputStream blocks on the subsequent read the XML already returned is 
not processed as soon as it could be. This is not a problem when reading a file 
as the XML is eventually processed when EOF is reached however if the XML is 
being streamed across a socket the BinInputStream never reaches EOF and the XML 
is not processed.

Sample program follows, see the comments in BinInputStream::readBytes, error 
checking etc is largely ignored for brevity.

#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/framework/XMLPScanToken.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <iostream>
#include <algorithm>
#include <unistd.h>

class Handler: public XERCES_CPP_NAMESPACE::DefaultHandler
{
        void warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
        {
                std::cout << "WARNING: " << 
XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage()) << 
std::endl;    
        }
        
    void error(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
    {
        std::cout << "ERROR: " << 
XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage())  << 
std::endl;
    }
    
    void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
    {
        std::cout << "FATAL ERROR: " << 
XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage())  << 
std::endl;
    }
 
    void endElement(const XMLCh* const uri, const XMLCh* const localname, const 
XMLCh* const qname)
    {
        std::cout << "END ELEMENT" << std::endl;
    }
    
    void startDocument()
    {
        std::cout << "START DOCUMENT" << std::endl;
    }
    
    void startElement(const XMLCh* const uri, const XMLCh* const localname, 
const XMLCh* const qname, const XERCES_CPP_NAMESPACE::Attributes& attrs)
    {
        std::cout << "START ELEMENT" << std::endl;
    }
};

class BinInputStream : public XERCES_CPP_NAMESPACE::BinInputStream
{
public:

        bool getIsOpen() const
        {
                return true;
        }

        unsigned int curPos() const
        {
                return 0;
        }
        
    unsigned int readBytes(XMLByte* const toFill, 
                                           const unsigned int maxToRead)
    {
        //
        // The first time this is called we return some valid XML which
        // should cause the parser to fire events. The second time it is
        // called we sleep to simulate a blocking read.
        //
        // Even though the parser has a valid chunk of XML it does not
        // fire any events other than start document.
        //
        // If the sleep is removed the parser gets EOF and fires the 
        // events as expected.
        //
        static size_t callCount = 0;
        
        if(callCount > 0)
        {
                sleep(10000);
                return 0;
        }
        
        ++callCount;
        
        std::string xml
        (
        "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>"
        "<document>"
        "       <element/>"
        "</document>"
        );      
        
                std::copy(xml.begin(),
                                  xml.end(),
                                  toFill);
                                  
        return xml.size();
    }

};

class InputSource : public XERCES_CPP_NAMESPACE::InputSource
{
public:

        virtual XERCES_CPP_NAMESPACE::BinInputStream* makeStream() const
        {
                return new BinInputStream;              
        }

};



int main(int argc, char** argv)
{
        XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();

        XERCES_CPP_NAMESPACE::SAX2XMLReader* reader = 
XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader();

        Handler* handler = new Handler;

        reader->setContentHandler(handler);
    reader->setErrorHandler(handler);   
    
    XERCES_CPP_NAMESPACE::XMLPScanToken scanToken;

        InputSource* inputSource = new InputSource;
        
        if(!reader->parseFirst(*inputSource, scanToken))
                return 1;
        
        while(reader->parseNext(scanToken));
        
        return 0;       
}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to