Search code examples
c++xmlxerces

Xerces C++: no error for non-existent file


I'm using the Xerces C++ DOM parser to read some XML files in a Visual C++ project. I have a class with a parse() method that is supposed to read and validate my XML source file. This is what the method looks like:

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>           
#include <xercesc/parsers/XercesDOMParser.hpp>  
#include <xercesc/framework/LocalFileInputSource.hpp>

using namespace std;
XERCES_CPP_NAMESPACE_USE

unsigned long RulesParser::parse( const wstring &xmlFile )
{
  if( parserInitialized_ == false ) {
    try {
      XMLPlatformUtils::Initialize();   /* initialize xerces */
    } catch( XMLException const &e ) {
      return Status::PARSER_INIT_FAIL;
    }
  }
  parserInitialized_  = true;           /* indicate xerces has been 
                                           successfully initialized */

  if( pDOMParser_ != NULL ) {
    delete pDOMParser_;
  }
  pDOMParser_ = new XercesDOMParser;    /* create a DOM parser instance */
  /* set xerces options */
  pDOMParser_->setDoNamespaces( true ); /* enable namespace processing */
  pDOMParser_->setDoSchema( true );     /* enable schema processing */
  pDOMParser_->setValidationScheme( XercesDOMParser::Val_Always );  /* parser always validates */
  pDOMParser_->setValidationSchemaFullChecking( true ); /* enable full schema checking */

  auto_ptr< LocalFileInputSource > srcFile; /* XML source file loader */

  try {
    srcFile.reset( new LocalFileInputSource( xmlFile.c_str() ) );

  } catch( const XMLException &e ) {
    return Status::XML_SOURCE_LOAD_ERROR;
  }

  /* parse the file */
  try {
    pDOMParser_->parse( *srcFile );

  } catch( const XMLException &e ) {    
    return Status::XML_SOURCE_PARSE_ERROR;

  } catch( const DOMException &e ) {
    return Status::XML_SOURCE_PARSE_DOM_ERROR;
  }

  return Status::OK;
}

The documentation for LocalFileInputSource says the constructor will throw an XMLException if the path doesn't resolve to a file. However, I can call this method with any arbitrary string and it executes to the end without any exceptions being raised. What am I doing wrong?

Also, the documentation for XercesDOMParser::parse() says a SAXException is one of the types of exceptions that it can throw. I find this confusing because from what I understand DOM and SAX parsers are 2 different animals, so why would the DOM parser throw a SAX exception?


Solution

  • See ErrorHandler documentation.

    You must declare and define a class that inherits from ErrorHandler and implements its virtual methods (or you can extend the HandlerBase class).

    Then you must call setErrorHandler on your parser instance passing an instance of your error handler, i.e. pDOMParser_->setErrorHandler(your_handler_instance).

    Example usage from Xerces-C++ trunk samples: rows 231-233 of SAXPrint.cpp.

    Update: example of custom error handler below.

    #include <iostream>
    #include <xercesc/sax/HandlerBase.hpp>
    XERCES_CPP_NAMESPACE_USE
    
    class CustomErrorHandler : public HandlerBase
    {
    
        public:
    
            CustomErrorHandler() {}
    
            void error(const SAXParseException& e)
            {
                handler(e);
            }
    
            void fatalError(const SAXParseException& e)
            {
                handler(e);
            }
    
            void warning(const SAXParseException& e)
            {
                handler(e);
            }
    
        private:
    
            void handler(const SAXParseException& e)
            {
                char* message = XMLString::transcode(e.getMessage());
    
                cerr << "line " << e.getLineNumber()
                     << ", column " << e.getColumnNumber()
                     << " -> " << message << "\n\n";
    
                XMLString::release(&message);
            }
    };