{"id":549,"date":"2010-01-21T11:54:42","date_gmt":"2010-01-21T11:54:42","guid":{"rendered":"http:\/\/www.codingfriends.com\/?p=549"},"modified":"2010-01-21T11:55:12","modified_gmt":"2010-01-21T11:55:12","slug":"xml-reader-full-cpp","status":"publish","type":"post","link":"https:\/\/www.codingfriends.com\/index.php\/2010\/01\/21\/xml-reader-full-cpp\/","title":{"rendered":"XML reader full &#8211; cpp"},"content":{"rendered":"<p>Here is the full code for the header and class file from the <a href=\"http:\/\/www.codingfriends.com\/index.php\/projects\/xml-reader-cpp\/\">xml reader<\/a> project<\/p>\n<p>Here is the cppxmlreader.h file.<\/p>\n<pre lang=\"cpp\">\r\n#ifndef CPPXMLREADER_H\r\n#define CPPXMLREADER_H\r\n\r\n#include <string>\r\n#include <vector>\r\n\r\n\/\/ using the namespace std for the string type, vector\r\nusing namespace std;\r\n\r\nconst int CHARACTERLENGHT = 80;\r\nconst string BADXMLVERSION = \"Xml version - first line ? - problem\";\r\nconst string BADTAGNAME = \"Tag name was not present\";\r\nconst string BADXMLTAGEND = \"End tag is not the same as tag name\";\r\nconst string BADATTRIBUTE = \"Attribute in wrong format attributeName=\\\"attributeValue\\\"\";\r\n\r\nstruct xmlAttribute {\r\n    string _attributeName, _attributeValue;\r\n};\r\n\r\nclass xmlObject {\r\n  private :\r\n    string _tagName, _tagValue;\r\n    vector<xmlAttribute> _attributes;\r\n    bool _xmlMainDetails;\r\n    \r\n  public:\r\n      xmlObject() { _xmlMainDetails = false;} ;\r\n      xmlObject(string tag, string tValue, xmlAttribute attribute);\r\n      \r\n      void setTagName(string tagName);\r\n      void setTagValue(string tagValue);\r\n      void addAttributes(xmlAttribute attribute);\r\n      void setAttributeVector(vector<xmlAttribute> setAtt);\r\n      void setXmlMainDetails(bool value);\r\n      bool getXmlMainDetails();\r\n      void printOutXmlObject();\r\n};\r\n\r\nclass xmlReader {\r\n  protected:\r\n    vector<xmlObject> _xmlMainDetails;\r\n    vector<xmlObject> _xmlDetails;\r\n    \r\n  public: \r\n    xmlReader();\r\n    \r\n    \/\/ open file and read in the xml file and place into the _xmlDetails\r\n    bool loadFile(string filename);\r\n    void printOuterXML();\r\n    \r\n  private :\r\n    xmlObject readLine(string xmlToSplitUp, string* tagName);\r\n    string readUntilCharacter(string line, char characterStart, char characterEnd, string *returnLine);\r\n    xmlAttribute getAttribute(string attributeString);\r\n    vector<xmlAttribute> getAttributesFromString(string str);\r\n};\r\n\r\n\r\n#endif \/\/ CPPXMLREADER_H\r\n<\/pre>\n<p>Here is the cppxmlreader.cpp file<\/p>\n<pre lang=\"cpp\">\r\n#include \"cppxmlreader.h\"\r\n#include <iostream>\r\n#include <string.h>\r\n#include <fstream>\r\n\r\nusing namespace std;\r\n\r\n\/* xmlObject *\/\r\n\/\/ constructor for xmlObject, if any details are passed whilst constructing \r\nxmlObject::xmlObject(string tag, string tValue, xmlAttribute attribute)\r\n{\r\n  _tagName = tag;\r\n  _tagValue = tValue;\r\n  _attributes.push_back(attribute);\r\n}\r\n\r\n\/\/ xml <tagname attributes=\"attributesvalue\">VALUE<\/tagname>\r\n\/\/ set the tag name\r\nvoid xmlObject::setTagName(string tagName)\r\n{\r\n  _tagName = tagName;\r\n}\r\n\r\n\/\/ set tag value\r\nvoid xmlObject::setTagValue(string tagValue)\r\n{\r\n  _tagValue = tagValue;\r\n}\r\n\r\n\/\/ add attributes to the vector attributes variable\r\nvoid xmlObject::addAttributes(xmlAttribute attribute)\r\n{\r\n  _attributes.push_back(attribute);\r\n}\r\n\r\n\/\/ fill in the vector attributes variable.\r\nvoid xmlObject::setAttributeVector(vector<xmlAttribute> setAtt)\r\n{\r\n  _attributes = setAtt;\r\n}\r\n\r\n\/\/ print out the xml object detais, with the attributes values.\r\nvoid xmlObject::printOutXmlObject()\r\n{\r\n  cout << \"XML Object\" << endl;\r\n  cout << \"Tagname  :\" << _tagName << endl;\r\n  cout << \"Tagvalue :\" << _tagValue << endl;\r\n  for (int i= 0; i < (int)_attributes.size(); i++)\r\n  {\r\n      cout << \"Attribute \" << i << \" : Name : \"<< _attributes.at(i)._attributeName << \" Value : \" << _attributes.at(i)._attributeValue << endl;\r\n  }\r\n}\r\n\r\n\/\/ set the main set details value\r\nvoid xmlObject::setXmlMainDetails(bool value)\r\n{\t\r\n    _xmlMainDetails = value;\r\n}\r\n\r\n\/\/ get a boolean value to see if the xmlObject is the main <?xml .. ?> value\r\nbool xmlObject::getXmlMainDetails()\r\n{\r\n  return _xmlMainDetails;\r\n}\r\n\r\n\r\n\/*xmlReader*\/\r\nxmlReader::xmlReader()\r\n{\r\n}\r\n\r\n\/\/ attribute is normally in the format of attributeName=\"attributeValue\"\r\nxmlAttribute xmlReader::getAttribute(string attributeString)\r\n{\r\n  xmlAttribute returnAttribute;\r\n  \r\n  \/\/ make sure that there is a = in the attribute string\r\n  int findEqual = attributeString.find('=');\r\n  if (findEqual > 0)\r\n  {\r\n    \/\/ set the attribute name to the substring till the equal\r\n    returnAttribute._attributeName = attributeString.substr(0,findEqual);\r\n    \/\/ make sure that there is some characters after the '=' sign.\r\n    if (attributeString.length() > (findEqual+3))\r\n    {\r\n      returnAttribute._attributeValue = attributeString.substr(findEqual+2,(attributeString.length() - (findEqual +3)));\r\n    }\r\n    else\r\n      throw BADATTRIBUTE;\r\n  }else\r\n    \/\/ if there does not appear to be =\"\" at the end of the string then throw a error.\r\n    throw BADATTRIBUTE;\r\n\r\n  return returnAttribute;\r\n}\r\n\r\nvector<xmlAttribute> xmlReader::getAttributesFromString(string str)\r\n{\r\n    vector<xmlAttribute> returnAtt;\r\n    xmlAttribute attribute;\r\n    int args;\r\n    char st1[CHARACTERLENGHT];\r\n    \r\n    \/\/ args normally equals 1 because there is a attribute present\r\n    \/\/ else there was no attribute there, just do one at a time\r\n    args = sscanf(str.c_str(), \"%s\", st1);\r\n    while (args  == 1 && (str.length() > 1)) {\r\n      \/\/ see if there is a real attribute attributeName=\"attributeValue\"\r\n      try {\r\n\tattribute = getAttribute(st1);\r\n\t\/\/ push back in the vector array the attribute\r\n\treturnAtt.push_back(attribute);\r\n      } catch (string errorStr)\t\t\/\/ any errors\r\n      {\r\n\tcout << \"ERROR : \" << errorStr << endl;\r\n      }\r\n      \/\/ re-do the string to pull out any more attributes.\r\n      str = str.substr(strlen(st1));\r\n      \/\/ see if there is any more attributes present.\r\n      args = sscanf(str.c_str(), \"%s\", st1);\r\n    }\r\n    return returnAtt;\r\n}\r\n\r\n\/\/ scan through the xml string and pull out the tags and the attributes and value.\r\nxmlObject xmlReader::readLine(string xmlToSplitUp, string* tagName)\r\n{\r\n  xmlObject returnObj;\r\n  string returnLine, value, endTagName;\r\n  int findXml;\r\n  \r\n  \/\/ pick out the tag name, if none then return and throw a bad tag name error.\r\n  *tagName = readUntilCharacter(xmlToSplitUp, '<','>', &returnLine);\r\n  if (tagName->length() ==0)\r\n  {\r\n     throw BADTAGNAME;\r\n     return returnObj;\r\n  }\r\n\r\n  \/\/ if there is a xml version etc in the tagname then process the xml version encoding values.\r\n  findXml=tagName->find(\"xml\");\r\n  if ((findXml > 0 && findXml < tagName->length()) && tagName->length() > 1 )\r\n  {\r\n    \/\/ this is the xml version etc.\r\n    \/\/ there should be ? at each end of the xml version statement\r\n    string xmlStr = readUntilCharacter(*tagName, '?','?', &returnLine);\r\n    if (returnLine != \"?\") \r\n    {\r\n      throw BADXMLVERSION;\r\n      return returnObj;\r\n    }\r\n    \/\/ go passed the xml characters.\r\n    returnLine = xmlStr.substr(findXml+3);\r\n    \/\/ read any of the attributes from the string\r\n    returnObj.setAttributeVector(getAttributesFromString(returnLine));\r\n    \/\/ I am storing the version and any other xml details, so set the return value to store in the correct place.\r\n    returnObj.setXmlMainDetails(true);\r\n  }else if (tagName->length() > 1) \r\n  {\r\n    \/\/ need to see if there is any attributes\r\n    int findTagAtts = tagName->find(' ');\r\n    if (findTagAtts < tagName->length())\r\n    {\r\n      \/\/ the attributes are passed the space character in the tagName variable\r\n      string attributes = tagName->substr(findTagAtts);\r\n      \/\/ store only the tagName in the tagName variable since pulled out the attributes\r\n      *tagName = tagName->substr(0,findTagAtts);\r\n      \/\/ get the attributes into a vector and store in the return object\r\n      returnObj.setAttributeVector(getAttributesFromString(attributes));\r\n    }\r\n\r\n    if (returnLine.length() > 1)\r\n    {\r\n      \/\/ pull out the value in the xml line <tagname>VALUE<\/tagname>\r\n      value = readUntilCharacter(returnLine,'>','<',&#038;returnLine);\r\n      returnObj.setTagValue(value);\r\n    }\r\n    if (returnLine.length() > 1)\r\n    {\r\n      \/\/ pick out the end tag name and make sure it is the same as the first one.\r\n      endTagName = readUntilCharacter(returnLine,'<','>',&returnLine);\r\n      string compareEndTag = \"\/\"+*tagName;\r\n      \/\/if the end tag is not the same as the tag name then throw a error.\r\n      if (endTagName != compareEndTag) \r\n      {\r\n\tthrow BADXMLTAGEND;\r\n      } \r\n    }\r\n    returnObj.setTagName(*tagName);\r\n\r\n   }\r\n  return returnObj;\r\n}\r\n\r\n\/\/ pick out the characters between two character points, and also return the rest of the line.\r\nstring xmlReader::readUntilCharacter(string line, char characterStart, char characterEnd, string *returnLine)\r\n{\r\n  string returnString;\r\n  \/\/ find the first occurrence of the character integer placement\r\n  int firstChar = line.find(characterStart);\r\n  \/\/ if there is one.\r\n  if (firstChar >= 0)\r\n  {\r\n    \/\/ setup the return string, even if a second part cannot be found.\r\n    returnString = line.substr(firstChar+1, (line.length()- firstChar)-1);\r\n    int secChar = returnString.find(characterEnd);\r\n    \/\/if the secound part can be found\r\n    if (secChar > 0)\r\n    {\r\n      *returnLine = returnString.substr(secChar, (returnString.length() - secChar));\r\n      returnString = returnString.substr(0,secChar);\r\n    }\r\n  }\r\n  return returnString;\r\n}\r\n\r\n\/\/ read in the XML file and place each line into the vector xmlObject \r\nbool xmlReader::loadFile(string filename)\r\n{\r\n  xmlObject xmlObj;\r\n  string line, tagName;\r\n  \r\n  ifstream xmlfile(filename.c_str());\r\n  if (xmlfile.is_open())\r\n  {\r\n      \/\/ if the xml version and also the encodingvalues are present.\r\n      \/\/getline(xmlfile,line);\r\n      \r\n      while (!xmlfile.eof())\r\n      {\r\n\t  \/\/ pull out the start tag and compare against the endtag\r\n\t  getline(xmlfile,line);\r\n\t  try \r\n\t  {\r\n\t    \/\/ pick out the xml details from line and return a xmlObject \r\n\t    \/\/ to add to the vector array of xml objects\r\n\t    \/\/ also return the tagName if any futher processing is required.\r\n\t    xmlObj = readLine(line, &tagName);\r\n\t    \/\/ if there is ?xml version etc details present store, else store into the main xml details\r\n\t    if (xmlObj.getXmlMainDetails())\r\n\t    {\r\n\t      _xmlMainDetails.push_back(xmlObj);\r\n\t    }\r\n\t    else\r\n\t    {  \r\n\t      _xmlDetails.push_back(xmlObj);\r\n\t    }\r\n\t  }\r\n\t  \/\/ if any error occur during the reading of the xml line.\r\n\t  catch (string errorStr)\r\n\t  {\r\n\t    cout << \"ERROR : \" << errorStr << endl;\r\n\t  }\r\n      }\r\n    \r\n      xmlfile.close();\r\n  }\r\n  else\r\n  {\r\n      cout << \"Unable to open the file\" << endl;\r\n  }\r\n}\r\n\r\n\/* print Out the outer XML values *\/\r\nvoid xmlReader::printOuterXML()\r\n{\r\n    cout << \"XML Reader Main Object (Xml main details) \" << endl;\r\n    for (int i =0; i < _xmlMainDetails.size(); i++)\r\n      _xmlMainDetails.at(i).printOutXmlObject();\r\n    \r\n    cout << \"XML Reader xml details\" << endl;\r\n    for (int i =0; i < _xmlDetails.size(); i++)\r\n      _xmlDetails.at(i).printOutXmlObject();\r\n}\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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 = &#8220;Xml version &#8211; first line ? &hellip; <a href=\"https:\/\/www.codingfriends.com\/index.php\/2010\/01\/21\/xml-reader-full-cpp\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">XML reader full &#8211; cpp<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[63,60],"class_list":["post-549","post","type-post","status-publish","format-standard","hentry","category-c_and_cpp","tag-reader","tag-xml"],"_links":{"self":[{"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/posts\/549","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/comments?post=549"}],"version-history":[{"count":2,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/posts\/549\/revisions"}],"predecessor-version":[{"id":551,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/posts\/549\/revisions\/551"}],"wp:attachment":[{"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/media?parent=549"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/categories?post=549"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codingfriends.com\/index.php\/wp-json\/wp\/v2\/tags?post=549"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}