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:



Saturday, 13 October 2012

Xerces for C++ Using Visual Studio 2010


It has been long since the last updates to this blog. I am in process of using Xerces-C++ for doing some coding and am going to write some posts on that. Clearly I have to say that this is my attempt to learn and I will be making lots of mistakes as a result. Having said that I am hoping that some of the people who are experts will correct me and provide good suggestions, better solutions.

I am also happy if someone else wants to write some blog posts on this topic or general C++ as long as there are enough examples to get your point across.

My Configuration:

Visual Studio 2010

Xerces is xerces-c-3.1.1-x86-windows-vc-10.0 that I have installed (copied) at: C:\Program Files. Downloaded from http://xerces.apache.org/xerces-c/download.cgi

The following will need to be added in the properties
In Include Directories add - C:\Program Files\xerces-c-3.1.1-x86-windows-vc-10.0\include;
In Library Directories add - C:\Program Files\xerces-c-3.1.1-x86-windows-vc-10.0\lib;
In Additional dependancies add - xerces-c_3D.lib; --> Note that this is for Debug configuration, for Release configuration you will need the release .lib

I also use Notepad++ to write XML files manually, available at: http://notepad-plus-plus.org/

The directory structure for the code is as follows
/
---Sample01/
---Sample02/
---XML/
   ---books.xml
   ---xyz.xml

I will be using the xml files in XML directory and if needed will write output there  
 
These programs will use XML and DOM so its a good idea to learn a bit about it. Use the link for XML and DOM.
http://www.w3schools.com/xml/
http://www.w3schools.com/dom/default.asp

Here are some of the other sites (working list) I am following for this topic and will be referring to examples from here.

http://www.yolinux.com/TUTORIALS/XML-Xerces-C.html
http://www.codeproject.com/Articles/31088/Xerces-for-C-Tutorial-Using-Visual-C
http://www.codeproject.com/Articles/32762/Xerces-for-C-Using-Visual-C-Part-2

Saturday, 18 June 2011

On vacation from coding


I am taking a vacation from coding and as a result, I may not be updating the blog for some time to come.

I will still try my best to moderate the comments and reply to them as far as possible.

If you are interested in C++, I recommend that you join the C++ professional group on Linkedin and there are lots of interesting discussions going on, on a regular basis. There is also the other websites page that links other interesting sites on C++.

For the time being, Adieu!

Tuesday, 14 June 2011

When true != true

If we define a boolean variable, say:
bool xyz;

then when we have to do some kind of a comparison we may do this as follows:
if(xyz == true)

When I used to be a new programmer, I used to always do this as follows:
if(true == xyz)

I think the way I did it is more robust and less error prone because you can by mistake do as follows:
if(xyz = true) //Single = instead of ==

The problem with my approach is that the code readability is affected and most people hate to see code like this. Instead, I started doing what normal people would do but making sure that I always use '==' and not '='.

Now some of you may be thinking why not:
if(xyz)

True, in case of Boolean this is a simplest way to do it and I had personally no problem with it until recently. While reviewing some code, I noticed that an engineer had changed a piece of code from:
if(xyz == true) to if(xyz)

Initially I thought that it may be that he did not like the '==' as its redundant. So when I checked his other code, I realised that he may have done this for a reason. Executing his code in the debug mode worked fine. So I changed:
if(xyz) back to if(xyz == true) and lo and behold, the test started to fail.

Putting a breakpoint I can see that while on the statement:
if(xyz == true)
the debugger shows xyz is 'true' but the comparison fails.

As usual digging into the problem further, I found that in one of the constructors, xyz was not initialised and the default garbage value appeared to show it as 'true'.

So its again got me into thinking that it may be better to write if(xyz == true) instead of if(xyz) as it may help in catching uninitialised variables. The best thing of course would be to make sure all variables in the class, whether public, protected or private are initialised.

Opinions welcome!

Tuesday, 7 June 2011

Multisets and Multimaps

I was trying to understand where multisets would be used as compared to multimaps and I didnt find any straightforward answer. I found this simple explanation at StackOverflow:

multimap

  • With ZIP code as a key, all people which have that ZIP code
  • With account ID as key, all open orders of that person/account
  • A dictionary, with per keyword various explanations

multiset

is in essence a map with a key and a integer count.

  • The inventory of a shop, all products have their key and the amount still available is the value
  • accumulated sales data of a shop, every time a product is sold the product id get's added to the multiset thereby increasing the amount sold

As a result I created this example below. This is probably not the best of examples but I didnt want to change it. The main problem below is that multimap's are not strictly speaking required in the example below. I could have used a map. Multimap would be needed if there was no quantity_ in the class and then I can add the products one by one. I could have then used the count method to get the quantity.

Anyway, program as follows:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Simple example of multiset

#include <iostream>
#include <string>
#include <set>
#include <map>
#include <algorithm>

using namespace
std;

class
Product //Keeping this simple
{
public
:
Product(string name, int code, int price) :
name_(name), productCode_(code), price_(price)
{

quantity_ = 10; //Lets fix this value for simplicity
}
bool
availableForSale()
{

if
(quantity_ > 0)
{

quantity_--;
return
true;
}

return
false;
}

string name_;
int
productCode_;
int
price_;
int
quantity_;
private
:
Product(); //Disabled the default constructor
};

void
sellProduct(string name, multimap<string, Product*>& inventory, multiset <int> &soldItems)
{

multimap<string, Product*>::iterator it = inventory.find(name);
if
(it != inventory.end())
{

if
((*it->second).availableForSale())
{

soldItems.insert((*it->second).productCode_);
}
}

else

{

cout << "Unknown product : " << name << endl;
}
}


void
soldItemsList(multimap<string, Product*>& inventory, multiset <int> &soldItems)
{

multimap<string, Product*>::iterator it = inventory.begin();
for
(it = inventory.begin(); it != inventory.end(); ++it)
{

int
soldCount = soldItems.count((*it->second).productCode_);
cout<<"Product = " << (*it->second).name_ << ", Quantity Sold = " << soldCount << endl;
}
}


int
checkSales(multimap<string, Product*>& inventory, multiset <int> &soldItems)
{

int
totalSales = 0;
multimap<string, Product*>::iterator it;
for
(it = inventory.begin(); it != inventory.end(); ++it)
{

int
soldCount = soldItems.count((*it->second).productCode_);
totalSales += soldCount * (*it->second).price_;
}

return
totalSales;
}


int
main()
{

//There is no special reason to use multimap instead of a map
//If you wanted to add same product and create quantity multimap is required
multimap<string, Product*> inventory;
Product* prod1 = new Product("product1", 2334, 10);
Product* prod2 = new Product("product2", 4556, 50);
inventory.insert(pair<string, Product*>("product1",prod1));
inventory.insert(pair<string, Product*>("product2",prod2));

multiset <int> soldItems;

sellProduct("product1", inventory, soldItems);
sellProduct("product2", inventory, soldItems);
sellProduct("apple", inventory, soldItems);
sellProduct("product1", inventory, soldItems);
sellProduct("product1", inventory, soldItems);
sellProduct("product2", inventory, soldItems);

soldItemsList(inventory, soldItems);

cout<<"Total sales = " << checkSales(inventory, soldItems) << endl;

delete
prod1;
delete
prod2;
return
0;
}



The output as follows:

Thursday, 2 June 2011

Example of Multisets

Took this one from Java2s and modified it slightly to show a bit more info.

Example as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Simple example of multiset

#include <iostream>
#include <set>
#include <algorithm>

using namespace
std;

int
main()
{

int
a[ 10 ] = { 7, 22, 9, 1, 18, 30, 100, 22, 85, 13 };
int
aSize = sizeof(a) / sizeof(int);
std::multiset< int, std::less< int > > intMultiset(a, a + aSize);

cout << "Printing out all the values in the multiset : ";
multiset<int>::iterator it;
for
( it = intMultiset.begin(); it != intMultiset.end(); ++it)
cout << " " << *it;
cout << endl << endl;

std::ostream_iterator< int > output( cout, " " );

cout << "There are currently " << intMultiset.count( 15 )
<<
" values of 15 in the multiset\n\n";

intMultiset.insert( 15 );
intMultiset.insert( 15 );

cout << "After two inserts, there are currently " << intMultiset.count( 15 )
<<
" values of 15 in the multiset\n\n";

cout << "Printing out all the values in the multiset : ";
for
( it = intMultiset.begin(); it != intMultiset.end(); ++it)
cout << " " << *it;
cout << endl << endl;

return
0;
}



Output as follows:

Wednesday, 25 May 2011

'auto' and 'register' variables

One of the questions that is still being asked in the interviews is about 'auto variables' and 'register variables'. I have never come across any practical code that uses them and dont even see any need for them being used but as I say, Interview questions dont reflect how good a coder would be and even if a person answers all questions correctly, how can we judge someone's debugging skills.

Anyway, 'auto' variables are the default local variables. When you define a local variable, it is by default 'auto'. There is no need to use it as its implicit. In the new C++ standard, C++0x, 'auto' serves another purpose and may break any C++ code using auto when compiled using C++0x.

The 'register' keyword was initially used to help the compiler optimise the performance for the variables that were read/written very often. Since the compilers have evolved, nowadays they choose to ignore the requests as they can optimize the performance better than us humans.

The following is from StackOverflow discussion:

Here's an excerpt from Section 6.7.1 (footnote 101) of the C99 standard (pdf):

The implementation may treat any register declaration simply as an auto declaration. However,whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifier register cannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.3.2) or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1). Thus, the only operator that can be applied to an array declared with storage-class specifier register is sizeof.

And from Section 7.1.1, Paragraph 3 of the C++ standard (pdf):

A register specifier has the same semantics as an auto specifier together with a hint to the implementation that the object so declared will be heavily used. [Note: the hint can be ignored and in most implementations it will be ignored if the address of the object is taken. —end note]

So, this seems like another case of C and C++ having "identical" features that behave the way you'd expect them most of the time, but diverge and cause confusion other times. In this situation, I think the way C does it makes sense since it

  • is semantically closest to being correct and;
  • doesn't do things behind your back.

Fun tidbits about register

The C++ group (WG21) wants to deprecate register:

The register keyword serves very little function, offering no more than a hint that a note says is typically ignored. It should be deprecated in this version of the standard, freeing the reserved name up for use in a future standard, much like auto has been re-used this time around for being similarly useless.

Notes from the March, 2009 meeting:

The consensus of the CWG was in favor of deprecating register.

Look what the C99 group (WG14) said about register (pdf) at a meeting:

General agreement to deprecate the “auto” keyword. Should we ask WG21 to go back to the previous use of “register” (no address)? No, this will not fly with WG21.


Sample program as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>

using namespace
std;

int
main()
{

int
i = 123;
auto
int j = 456;
register
int k = 789;

cout<<"Address of i = " << &i <<", Value = " << i << endl;
cout<<"Address of j = " << &j <<", Value = " << j << endl;
cout<<"Address of k = " << &k <<", Value = " << k << endl;

return
0;
}



Output as follows:
Note that the address of i, j and k are very close implying that the compiler chose to ignore the 'register' keyword.

Wednesday, 11 May 2011

Example of set_union and set_intersection

Program as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>

using namespace
std;

int
main()
{

int
setOne[] = {5, 10, 15, 20, 25};
int
setTwo[] = {50, 40, 30, 20, 10, 11, 21, 31, 41, 51};

int
setOneSize = sizeof(setOne) / sizeof(int);
int
setTwoSize = sizeof(setTwo) / sizeof(int);

//Its necessary to sort if not already sorted
sort(setTwo, setTwo + setTwoSize);

vector<int> unionSetVector(setOneSize + setTwoSize);
set_union(setOne, setOne + setOneSize, setTwo, setTwo + setTwoSize, unionSetVector.begin());

cout<<"\n1. unionSetVector : ";
copy(unionSetVector.begin(), unionSetVector.end(), ostream_iterator<int>(cout, " "));
cout<<endl;

vector<int> intersectionSetVector(min(setOneSize, setTwoSize));
set_intersection(setOne, setOne + setOneSize, setTwo, setTwo + setTwoSize, intersectionSetVector.begin());

cout<<"\n1. intersectionSetVector : ";
copy(intersectionSetVector.begin(), intersectionSetVector.end(), ostream_iterator<int>(cout, " "));
cout<<endl;

cout<<endl;
return
0;
}


The output is as follows:

Tuesday, 3 May 2011

Example of 'Set' and operations

Example of Set and operations as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
#include <set>

using namespace
std;

int
main()
{

int
someInts[] = {3, 6, 9, 12, 15, 18};
int
someIntsSize = sizeof(someInts) / sizeof(int);

set<int> someSet (someInts, someInts + someIntsSize);

cout<<"\n1. someSet : ";
copy(someSet.begin(), someSet.end(), ostream_iterator<int>(cout, " "));
cout<<endl;

//Insert some more elements
someSet.insert(0);
someSet.insert(10);
someSet.insert(20);

cout<<"\n2. someSet : ";
copy(someSet.begin(), someSet.end(), ostream_iterator<int>(cout, " "));
cout<<endl;

//Upper Bound means the next greater number
set<int>::iterator it = someSet.upper_bound(5);
cout << "\nupper_bound(5) = " << *it << endl;

it = someSet.upper_bound(10);
cout << "\nupper_bound(10) = " << *it << endl;

//Lower bound means either equal or greater number
it = someSet.lower_bound(5);
cout << "\nlower_bound(5) = " << *it << endl;

it = someSet.lower_bound(10);
cout << "\nlower_bound(10) = " << *it << endl;

//Equal Range returns a pair
pair<set<int>::iterator,set<int>::iterator> retIt;
retIt = someSet.equal_range(5);
cout<<"\nequal_range(5) - lower bound = " << *retIt.first <<
" upper bound = "
<< *retIt.second << endl;

retIt = someSet.equal_range(10);
cout<<"\nequal_range(10) - lower bound = " << *retIt.first <<
" upper bound = "
<< *retIt.second << endl;

cout<<endl;
return
0;
}


The output is as follows:

Wednesday, 27 April 2011

Example of Algorithm Copy

Sometimes its useful to know the 'copy' method in algorithm class. The following is an example:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy

//OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result );

#include<iostream>
#include <algorithm>
#include <vector>

using namespace
std;

int
main()
{

int
someInts[] = {10, 20, 20, 40, 50};
int
someMoreInts[] = {100, 200, 300, 400, 500, 600, 700};

vector<int> someVector;
vector<int>::iterator someIterator;

//Get the total size of all elements
int totalSize = (sizeof(someInts) + sizeof(someMoreInts)) / sizeof(int);

//Resize someVector to right size
someVector.resize(someVector.size() + totalSize);

//Get the number of elements of someInts
int tempSize = sizeof(someInts) / sizeof(int);

vector<int>::iterator finalElementIt = copy(someInts, someInts + tempSize, someVector.begin());

cout<<"\n1. someVector contains :";
for
(someIterator = someVector.begin(); someIterator != someVector.end(); ++someIterator)
cout<<" "<<*someIterator;
cout<<endl;

//Get size of someMoreInts
tempSize = sizeof(someMoreInts) / sizeof(int);

copy(someMoreInts, someMoreInts + tempSize, finalElementIt);

cout<<"\n2. someVector contains :";
for
(someIterator = someVector.begin(); someIterator != someVector.end(); ++someIterator)
cout<<" "<<*someIterator;
cout<<endl;

return
0;
}


The output is as follows: