Sunday 14 October 2012

Xerces: Reading an XML file and printing it out

As I mentioned in the Xerces introductory post, here is the first program:

I have created an XML file called books.xml located in the XML directory.

All the operations will be done in the DomReader class.

main.cpp

//Program tested on Microsoft Visual Studio 2010 - Zahid Ghadialy
//Example demonstrates reading an XML file and printing it out

 
#include <iostream>
#include <xercesc/dom/DOM.hpp>
#include "DomReader.h"

using namespace std;
 
 
int main()
{
  string xmlFileName="..\\..\\XML\\books.xml";
  
  DomReader myDomReader;
 
  try
  {
    myDomReader.readDomFile(xmlFileName);
  }
  catch (runtime_error e)
  {
    cout << e.what() <<endl;
  }
  catch(...)
  {
    cout << "Unexpected error occurred" << endl;
  }
 
  return 0;
}


DomReader.h

#include <string>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

using namespace std;
XERCES_CPP_NAMESPACE_USE
 
class DomReader
{
public:
  DomReader();
  ~DomReader();
 
  void readDomFile(std::string&) throw(std::runtime_error);
  
 
private:
  void convertDomToXmlString(DOMNode* domNode, std::string &) throw(std::runtime_error);
  string narrow( const wstring& str );
  xercesc::XercesDOMParser *domFileParser;
 
};


DomReader.cpp

#include <iostream>
#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
 
#include "DomReader.h"

 
DomReader::DomReader()
{
  XMLPlatformUtils::Initialize();
  domFileParser = new XercesDOMParser;
  domFileParser->setValidationScheme(XercesDOMParser::Val_Never);
  domFileParser->setDoNamespaces(false);    // optional
}
 
DomReader::~DomReader()
{
  if(domFileParser)
    delete domFileParser;
  XMLPlatformUtils::Terminate();
}
 
void DomReader::readDomFile(string& domFileName) throw(std::runtime_error)
{
  //Check if filename / file is good
  struct _stat fileStatus;
 
  int returnStat = _stat(domFileName.c_str(), &fileStatus);
  if ( returnStat == ENOENT )
    throw ( runtime_error("Path file_name does not exist, or path is an empty string.") );
  else if ( returnStat == ENOTDIR )
    throw ( std::runtime_error("A component of the path is not a directory."));
  else if( returnStat == ELOOP )
    throw ( std::runtime_error("Too many symbolic links encountered while traversing the path."));
  else if( returnStat == EACCES )
    throw ( std::runtime_error("Permission denied."));
  else if( returnStat == ENAMETOOLONG )
    throw ( std::runtime_error("File can not be read\n"));
  else if( returnStat == -1)
    throw ( std::runtime_error("Other Unknown Error\n"));
 
  //Parse the file
  domFileParser->parse(domFileName.c_str());
 
  //No need to free this pointer - owned by the parent parser object
  DOMDocument* xmlDoc = domFileParser->getDocument();
  if( !xmlDoc ) throw(std::runtime_error( "DOM document could not be opened" ));
 
  //Get the top-level element: Name is "root". No attributes for "root"
  DOMElement* elementRoot = xmlDoc->getDocumentElement();
  if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
 
  string xmlString;
  try
  {
    convertDomToXmlString(elementRoot, xmlString);
  }
  catch(runtime_error e)
  {
    throw(runtime_error(e));
  }
  cout << "DOM File: "<< domFileName << " output is as follows "<<endl;
  cout << xmlString;
  cout << endl;
}
 
void DomReader::convertDomToXmlString(DOMNode* domNode, string &xmlString) throw(std::runtime_error)
{
  try
  {
    DOMImplementation *domImpl = DOMImplementationRegistry::getDOMImplementation(L"LS");
    DOMLSSerializer   *domSerializer = ((DOMImplementationLS*)domImpl)->createLSSerializer();
    XMLCh *xmlBuffer = domSerializer->writeToString(domNode);
    xmlString = narrow(xmlBuffer);
    XMLString::release (&xmlBuffer);
    delete domSerializer;
  }
  catch(XMLException& e)
  {
    char *xmlErrMessage = XMLString::transcode(e.getMessage());
    throw runtime_error(xmlErrMessage);
  }
  catch(...)
  {
    throw runtime_error("Unknown error in convertDomToXmlString\n");
  }
}
 
string DomReader::narrow( const wstring& str )
{
  ostringstream stm ;    
  const ctype<char>& ctfacet = use_facet< ctype<char> >( stm.getloc() ) ;    
  for( size_t i=0 ; i<str.size() ; ++i )
    stm << ctfacet.narrow( str[i], 0 ) ;    
  return stm.str() ;
}


The output is as follows:



No comments:

Post a Comment