/** * XML Serialization * Simple and lightweight xml serialization class * * Original code by Lothar Perr * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any * purpose, including commercial applications, and to alter it and * redistribute it freely */ #pragma once #include "stdafx.h" #include #include #include #include #include "XMLSerialization.h" /** XML Serialization namespace */ namespace xmls { /** Assign a value to the xint member @return void */ void xInt::AssignValue(int value) { m_sValue =std::to_string(value); }; /** Returns the int-value of the xint member @return current value */ int xInt::value() { int value; value = std::stoi(m_sValue); return value; }; /** Returns the bool-value of the xbool member @return current value */ bool xBool::value() { bool value=false; std::string sHelp = m_sValue; transform(sHelp.begin(), sHelp.end(), sHelp.begin(), ::toupper); if (sHelp=="TRUE") return true; return value; }; /** Assign a value to the xTime_t member @return void */ void xTime_t::AssignValue(const time_t value) { m_sValue = std::to_string(value); } time_t xTime_t::value() { time_t t; t = std::stoi(m_sValue); return t; } /** Assign a value to the xOleDateTime member @return void */ void xOleDateTime::AssignValue(const COleDateTime value) { const CString MSR_RESULT_INFOR_YMD = _T("%Y-%m-%d %H:%M:%S"); m_sValue = value.Format (MSR_RESULT_INFOR_YMD); } COleDateTime xOleDateTime::value() { COleDateTime t; t.ParseDateTime(m_sValue.c_str()); return t; } void xOleDateTimeSpan::AssignValue(const COleDateTimeSpan a_TimeSpan) { CString strRet; strRet.Format("%f", a_TimeSpan.m_span); m_sValue = strRet; } COleDateTimeSpan xOleDateTimeSpan::value() { COleDateTimeSpan t; t.m_span = atof(m_sValue.c_str()); return t; } /** Delete all (self created) collection-elements @return void */ class Slo; void CollectionBase::Clear() { if (m_vCollection.size()>0) { m_vCollection.clear(); } } /** SerializableBase Constructor */ Slo::Slo() { m_sClassName.clear (); m_sVersion.clear(); m_sXML.clear(); m_AttributeMappings.clear(); m_MemberMappings.clear(); m_MemberCollections.clear(); } /** SerializableBase Destructor Clean Collections, Mappings and Subclass-Mappings */ Slo::~Slo() { if (m_MemberCollections.size()>0) { m_MemberCollections.clear(); } if (m_MemberMappings.size() > 0) { m_MemberMappings.clear(); } if (m_AttributeMappings.size() > 0) { m_AttributeMappings.clear(); } m_sXML.clear(); m_sClassName.clear (); m_sVersion.clear(); } /** Register a member @MemberName XML-Description/Name for the member @Member Member to register @return void */ void Slo::Register(std::string MemberName, MemberBase *Member, std::string DefaultValue) { m_AttributeMappings[MemberName] = Member; } /** Register a member-subclass @MemberName XML-Description/Name for the member-class @Member Member-class to register @return void */ void Slo::Register(std::string MemberName, ISlo *Member) { m_MemberMappings[MemberName] = Member; } /** Register a class-collection @CollectionName XML-Description/Name for the collection @SubclassCollection Collection to register @return void */ void Slo::Register(std::string CollectionName, CollectionBase *SubclassCollection) { SubclassCollection->setCollectionName(CollectionName); m_MemberCollections[CollectionName] = SubclassCollection; } /** Perform serialization @classDoc tinyxml Class Document @rootNode tinyxml Element rootNode @return void */ void Slo::toXML(tinyxml2::XMLDocument *classDoc, tinyxml2::XMLElement *rootNode) { for (auto it_member = m_AttributeMappings.begin() ; it_member != m_AttributeMappings.end(); ++it_member) { rootNode->SetAttribute(it_member->first.c_str(), it_member->second->c_str ()); } for (auto it_subclass = m_MemberMappings.begin() ; it_subclass != m_MemberMappings.end(); ++it_subclass) { ISlo *subMember = it_subclass->second; tinyxml2::XMLElement *subClassNode = classDoc->NewElement("Member"); subClassNode->SetAttribute("RegName", it_subclass->first.c_str()); rootNode->InsertEndChild(subClassNode); subMember->Serialize(true,classDoc, subClassNode); } for (CollectionIterator it_collection = m_MemberCollections.begin() ; it_collection != m_MemberCollections.end(); ++it_collection) { tinyxml2::XMLElement *listNode = classDoc->NewElement("Collection"); listNode->SetAttribute("RegName", (*it_collection).second ->getCollectionName().c_str()); for (size_t c=0;c<(*it_collection).second->size();c++) { ISlo *item = (*it_collection).second ->getItem(c); tinyxml2::XMLElement *elementNode = classDoc->NewElement("Member"); item->Serialize(true,classDoc, elementNode); listNode->InsertEndChild(elementNode); } rootNode->InsertEndChild(listNode); } } /** Perform deserialization @classItem destination object @classDoc tinyxml Class Document @rootNode tinyxml Element rootNode @return void */ void Slo::fromXML( tinyxml2::XMLDocument *classDoc, tinyxml2::XMLElement *rootNode) { for (auto it = this->m_AttributeMappings.begin(); it != this->m_AttributeMappings.end(); ++it) { if (rootNode->Attribute(it->first.c_str() )) { *(it->second->getStringPtr ()) = rootNode->Attribute(it->first.c_str());// *(*it)->getField() = memberNode->GetText(); } } tinyxml2::XMLElement *classNode = rootNode->FirstChildElement("Member"); while(classNode!=NULL) { std::string className = classNode->Attribute("RegName"); for (auto it_subclass = this->m_MemberMappings.begin(); it_subclass != this->m_MemberMappings.end(); ++it_subclass) { if (it_subclass->first == className) { it_subclass->second ->Serialize( false,classDoc, classNode); break; } } classNode = classNode->NextSiblingElement("Member"); } tinyxml2::XMLElement *collectionNode = rootNode->FirstChildElement("Collection"); while (collectionNode!=NULL) { std::string collectionName = collectionNode->Attribute("RegName"); for (CollectionIterator it_collection = this->m_MemberCollections.begin() ; it_collection != this->m_MemberCollections.end(); ++it_collection) { if ((*it_collection).second ->getCollectionName()==collectionName) { (*it_collection).second ->Clear(); tinyxml2::XMLElement *classNode = collectionNode->FirstChildElement("Member"); while (classNode!=NULL) { ISlo *newItem = (*it_collection).second ->newElement(); newItem->Serialize(false,classDoc, classNode); classNode = classNode->NextSiblingElement("Member"); } } } collectionNode = collectionNode->NextSiblingElement("Collection"); } } /** Get Class-Type of XML-Source @XMLSource XML-Input @return class name */ std::string Slo::IdentifyClass(std::string XMLSource) { tinyxml2::XMLDocument doc; doc.Parse(XMLSource.c_str(), (size_t)XMLSource.length()); tinyxml2::XMLElement* rootNode; rootNode = doc.FirstChildElement(RootClassName); if (rootNode) { const char* value = rootNode->Attribute("RegName"); if (value) return std::string(value); } return Empty_String; } /** Get Class-Version of XML-Source @XMLSource XML-Input @return class version */ std::string Slo::IdentifyClassVersion(std::string XMLSource) { tinyxml2::XMLDocument doc; doc.Parse(XMLSource.c_str(), (size_t)XMLSource.length()); tinyxml2::XMLElement* rootNode; rootNode = doc.FirstChildElement(RootClassName); if (rootNode) { const char* value = rootNode->Attribute("Version"); if (value) return std::string(value); } return Empty_String; } /** Search/Replace in a string @source source the source string @searchFor search for @replaceWith replace with @return the resulting string */ std::string Slo::strReplaceAll(std::string source, const std::string searchFor, const std::string replaceWith) { if(searchFor.empty()) return source; size_t start_pos = 0; while((start_pos = source.find(searchFor, start_pos)) != std::string::npos) { source.replace(start_pos, searchFor.length(), replaceWith); start_pos += replaceWith.length(); } return source; } void Slo::Clear() { m_AttributeMappings.clear (); m_MemberMappings.clear (); m_MemberCollections.clear (); } void xDouble::AssignValue(const double value) { m_sValue = std::to_string(value); } double xDouble::value() { double value; value = std::stod(m_sValue); return value; } void xLong::AssignValue(const long value) { m_sValue = std::to_string(value); } long xLong::value() { long value; value = std::stol(m_sValue); return value; } void xDWORD::AssignValue(const DWORD value) { m_sValue = std::to_string(value); } DWORD xDWORD::value() { DWORD value; value = std::stol(m_sValue); return value; } void xRect::AssignValue(const CRect value, int shape) {// domain text body CString strDomainTextBody = _T(""); // value 1 -- shape CString strValue; // value 2 -- center x // domain center strValue.Format("%d", (int)value.CenterPoint().x); strDomainTextBody += strValue + _T(","); // value 3 -- center y strValue.Format("%d", (int)value.CenterPoint().y); strDomainTextBody += strValue + _T(","); if (shape==0) { // value 4 -- diameter strValue.Format("%d", (int)value.Width ()); strDomainTextBody += strValue+ _T(","); // value 5 -- 0 strDomainTextBody += _T("0"); } else { // value 4 -- width strValue.Format("%d", (int)value.Width()); strDomainTextBody += strValue + _T(","); // value 5 -- height strValue.Format("%d", (int)value.Height()); strDomainTextBody += strValue ; } // return domain text body m_sValue= strDomainTextBody; } CRect xRect::value() {//here,we use the rectangle's left,top,right,bottom to memorize these four numbers.Infact they are centreX, centreY , diameter(width),0(height) if the shape is circle. //so when we get these numbers we must get left,top,right,bottom because they are just four numbers memory here temporarily. CRect rectangle; std::vector point; SplitString(m_sValue, point, ","); rectangle.left = stoi(point[0]); rectangle.top = stoi(point[1]); rectangle.right = stoi( point[2]); rectangle.bottom = stoi(point[3]); return rectangle; } void xPoint::AssignValue(const CPoint value) { int X = value.x; int Y= value.y; std::string OutString; std::string sX = std::to_string(X); std::string sY = std::to_string(Y); OutString = sX + "," + sY ; m_sValue = OutString; } CPoint xPoint::value() { CPoint p; std::vector point; SplitString(m_sValue, point, ","); p.x = stoi(point[0], 0, 0); p.y = stoi(point[1], 0, 0); return p; } void SplitString(const std::string& s, std::vector& v, const std::string& c) { std::string::size_type pos1, pos2; pos2 = s.find(c); pos1 = 0; while (std::string::npos != pos2) { v.push_back(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + c.size(); pos2 = s.find(c, pos1); } if (pos1 != s.length()) v.push_back(s.substr(pos1)); } std::vector SplitString(const std::string& s, const std::string& c) { std::string::size_type pos1, pos2; pos2 = s.find(c); pos1 = 0; std::vector v; while (std::string::npos != pos2) { v.push_back(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + c.size(); pos2 = s.find(c, pos1); } if (pos1 != s.length()) v.push_back(s.substr(pos1)); return v; } void ReplaceAll(std::string& content, std::string searchFor, std::string replaceWith) { if (searchFor.empty()) return ; size_t start_pos = 0; while ((start_pos = content.find(searchFor, start_pos)) != std::string::npos) { content.replace(start_pos, searchFor.length(), replaceWith); start_pos += replaceWith.length(); } return ; /*while (content.find(substr1) > 0) { content.replace(content.find(substr1), substr1.size(), substr2); }*/ } void ReplaceFirst(std::string& content, std::string searchFor, std::string replaceWith) { if (searchFor.empty()) return; size_t start_pos = 0; start_pos = content.find(searchFor, start_pos); if (start_pos != std::string::npos) { content.replace(start_pos, searchFor.length(), replaceWith); //start_pos += replaceWith.length(); } return; /*while (content.find(substr1) > 0) { content.replace(content.find(substr1), substr1.size(), substr2); }*/ } }