Here is the full code for the header and class file from the xml reader project
Here is the cppxmlreader.h file.
#ifndef CPPXMLREADER_H
#define CPPXMLREADER_H
#include
#include
// using the namespace std for the string type, vector
using namespace std;
const int CHARACTERLENGHT = 80;
const string BADXMLVERSION = "Xml version - first line ? - problem";
const string BADTAGNAME = "Tag name was not present";
const string BADXMLTAGEND = "End tag is not the same as tag name";
const string BADATTRIBUTE = "Attribute in wrong format attributeName=\"attributeValue\"";
struct xmlAttribute {
string _attributeName, _attributeValue;
};
class xmlObject {
private :
string _tagName, _tagValue;
vector _attributes;
bool _xmlMainDetails;
public:
xmlObject() { _xmlMainDetails = false;} ;
xmlObject(string tag, string tValue, xmlAttribute attribute);
void setTagName(string tagName);
void setTagValue(string tagValue);
void addAttributes(xmlAttribute attribute);
void setAttributeVector(vector setAtt);
void setXmlMainDetails(bool value);
bool getXmlMainDetails();
void printOutXmlObject();
};
class xmlReader {
protected:
vector _xmlMainDetails;
vector _xmlDetails;
public:
xmlReader();
// open file and read in the xml file and place into the _xmlDetails
bool loadFile(string filename);
void printOuterXML();
private :
xmlObject readLine(string xmlToSplitUp, string* tagName);
string readUntilCharacter(string line, char characterStart, char characterEnd, string *returnLine);
xmlAttribute getAttribute(string attributeString);
vector getAttributesFromString(string str);
};
#endif // CPPXMLREADER_H
Here is the cppxmlreader.cpp file
#include "cppxmlreader.h"
#include
#include
#include
using namespace std;
/* xmlObject */
// constructor for xmlObject, if any details are passed whilst constructing
xmlObject::xmlObject(string tag, string tValue, xmlAttribute attribute)
{
_tagName = tag;
_tagValue = tValue;
_attributes.push_back(attribute);
}
// xml VALUE
// set the tag name
void xmlObject::setTagName(string tagName)
{
_tagName = tagName;
}
// set tag value
void xmlObject::setTagValue(string tagValue)
{
_tagValue = tagValue;
}
// add attributes to the vector attributes variable
void xmlObject::addAttributes(xmlAttribute attribute)
{
_attributes.push_back(attribute);
}
// fill in the vector attributes variable.
void xmlObject::setAttributeVector(vector setAtt)
{
_attributes = setAtt;
}
// print out the xml object detais, with the attributes values.
void xmlObject::printOutXmlObject()
{
cout << "XML Object" << endl;
cout << "Tagname :" << _tagName << endl;
cout << "Tagvalue :" << _tagValue << endl;
for (int i= 0; i < (int)_attributes.size(); i++)
{
cout << "Attribute " << i << " : Name : "<< _attributes.at(i)._attributeName << " Value : " << _attributes.at(i)._attributeValue << endl;
}
}
// set the main set details value
void xmlObject::setXmlMainDetails(bool value)
{
_xmlMainDetails = value;
}
// get a boolean value to see if the xmlObject is the main value
bool xmlObject::getXmlMainDetails()
{
return _xmlMainDetails;
}
/*xmlReader*/
xmlReader::xmlReader()
{
}
// attribute is normally in the format of attributeName="attributeValue"
xmlAttribute xmlReader::getAttribute(string attributeString)
{
xmlAttribute returnAttribute;
// make sure that there is a = in the attribute string
int findEqual = attributeString.find('=');
if (findEqual > 0)
{
// set the attribute name to the substring till the equal
returnAttribute._attributeName = attributeString.substr(0,findEqual);
// make sure that there is some characters after the '=' sign.
if (attributeString.length() > (findEqual+3))
{
returnAttribute._attributeValue = attributeString.substr(findEqual+2,(attributeString.length() - (findEqual +3)));
}
else
throw BADATTRIBUTE;
}else
// if there does not appear to be ="" at the end of the string then throw a error.
throw BADATTRIBUTE;
return returnAttribute;
}
vector xmlReader::getAttributesFromString(string str)
{
vector returnAtt;
xmlAttribute attribute;
int args;
char st1[CHARACTERLENGHT];
// args normally equals 1 because there is a attribute present
// else there was no attribute there, just do one at a time
args = sscanf(str.c_str(), "%s", st1);
while (args == 1 && (str.length() > 1)) {
// see if there is a real attribute attributeName="attributeValue"
try {
attribute = getAttribute(st1);
// push back in the vector array the attribute
returnAtt.push_back(attribute);
} catch (string errorStr) // any errors
{
cout << "ERROR : " << errorStr << endl;
}
// re-do the string to pull out any more attributes.
str = str.substr(strlen(st1));
// see if there is any more attributes present.
args = sscanf(str.c_str(), "%s", st1);
}
return returnAtt;
}
// scan through the xml string and pull out the tags and the attributes and value.
xmlObject xmlReader::readLine(string xmlToSplitUp, string* tagName)
{
xmlObject returnObj;
string returnLine, value, endTagName;
int findXml;
// pick out the tag name, if none then return and throw a bad tag name error.
*tagName = readUntilCharacter(xmlToSplitUp, '<','>', &returnLine);
if (tagName->length() ==0)
{
throw BADTAGNAME;
return returnObj;
}
// if there is a xml version etc in the tagname then process the xml version encoding values.
findXml=tagName->find("xml");
if ((findXml > 0 && findXml < tagName->length()) && tagName->length() > 1 )
{
// this is the xml version etc.
// there should be ? at each end of the xml version statement
string xmlStr = readUntilCharacter(*tagName, '?','?', &returnLine);
if (returnLine != "?")
{
throw BADXMLVERSION;
return returnObj;
}
// go passed the xml characters.
returnLine = xmlStr.substr(findXml+3);
// read any of the attributes from the string
returnObj.setAttributeVector(getAttributesFromString(returnLine));
// I am storing the version and any other xml details, so set the return value to store in the correct place.
returnObj.setXmlMainDetails(true);
}else if (tagName->length() > 1)
{
// need to see if there is any attributes
int findTagAtts = tagName->find(' ');
if (findTagAtts < tagName->length())
{
// the attributes are passed the space character in the tagName variable
string attributes = tagName->substr(findTagAtts);
// store only the tagName in the tagName variable since pulled out the attributes
*tagName = tagName->substr(0,findTagAtts);
// get the attributes into a vector and store in the return object
returnObj.setAttributeVector(getAttributesFromString(attributes));
}
if (returnLine.length() > 1)
{
// pull out the value in the xml line VALUE
value = readUntilCharacter(returnLine,'>','<',&returnLine);
returnObj.setTagValue(value);
}
if (returnLine.length() > 1)
{
// pick out the end tag name and make sure it is the same as the first one.
endTagName = readUntilCharacter(returnLine,'<','>',&returnLine);
string compareEndTag = "/"+*tagName;
//if the end tag is not the same as the tag name then throw a error.
if (endTagName != compareEndTag)
{
throw BADXMLTAGEND;
}
}
returnObj.setTagName(*tagName);
}
return returnObj;
}
// pick out the characters between two character points, and also return the rest of the line.
string xmlReader::readUntilCharacter(string line, char characterStart, char characterEnd, string *returnLine)
{
string returnString;
// find the first occurrence of the character integer placement
int firstChar = line.find(characterStart);
// if there is one.
if (firstChar >= 0)
{
// setup the return string, even if a second part cannot be found.
returnString = line.substr(firstChar+1, (line.length()- firstChar)-1);
int secChar = returnString.find(characterEnd);
//if the secound part can be found
if (secChar > 0)
{
*returnLine = returnString.substr(secChar, (returnString.length() - secChar));
returnString = returnString.substr(0,secChar);
}
}
return returnString;
}
// read in the XML file and place each line into the vector xmlObject
bool xmlReader::loadFile(string filename)
{
xmlObject xmlObj;
string line, tagName;
ifstream xmlfile(filename.c_str());
if (xmlfile.is_open())
{
// if the xml version and also the encodingvalues are present.
//getline(xmlfile,line);
while (!xmlfile.eof())
{
// pull out the start tag and compare against the endtag
getline(xmlfile,line);
try
{
// pick out the xml details from line and return a xmlObject
// to add to the vector array of xml objects
// also return the tagName if any futher processing is required.
xmlObj = readLine(line, &tagName);
// if there is ?xml version etc details present store, else store into the main xml details
if (xmlObj.getXmlMainDetails())
{
_xmlMainDetails.push_back(xmlObj);
}
else
{
_xmlDetails.push_back(xmlObj);
}
}
// if any error occur during the reading of the xml line.
catch (string errorStr)
{
cout << "ERROR : " << errorStr << endl;
}
}
xmlfile.close();
}
else
{
cout << "Unable to open the file" << endl;
}
}
/* print Out the outer XML values */
void xmlReader::printOuterXML()
{
cout << "XML Reader Main Object (Xml main details) " << endl;
for (int i =0; i < _xmlMainDetails.size(); i++)
_xmlMainDetails.at(i).printOutXmlObject();
cout << "XML Reader xml details" << endl;
for (int i =0; i < _xmlDetails.size(); i++)
_xmlDetails.at(i).printOutXmlObject();
}