00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "freXMLStreamObject.h"
00023 #include "freExceptions.h"
00024 #include "freConvert.h"
00025
00026 #include "fstream"
00027
00028 #include <itksys/SystemTools.hxx>
00029
00030 namespace FREE
00031 {
00032
00033 const std::string XMLStreamObject::cXML_Text ="";
00034
00038
00039 void
00040 XMLStreamObject::
00041 CB_Static_StartElement(void* parser, const char *name,
00042 const char **pAttributes)
00043 {
00044
00045
00046
00047 static_cast<XMLStreamObject*>(parser)->CB_StartElement(name, pAttributes);
00048 }
00049
00050 void
00051 XMLStreamObject::
00052 CB_Static_EndElement(void* parser, const char *name)
00053 {
00054
00055
00056 static_cast<XMLStreamObject*>(parser)->CB_EndElement(name);
00057 }
00058
00059 void
00060 XMLStreamObject::
00061 CB_Static_CharacterDataHandler(void* parser, const char* data,
00062 int length)
00063 {
00064
00065
00066
00067 static_cast<XMLStreamObject*>(parser)->CB_CharacterDataHandler(data, length);
00068 }
00069
00070 void
00071 XMLStreamObject::
00072 LoadFromString(const std::string& rsRawData)
00073 {
00074 m_Parser = XML_ParserCreate(0);
00075 XML_SetElementHandler(m_Parser,&CB_Static_StartElement,&CB_Static_EndElement);
00076 XML_SetCharacterDataHandler(m_Parser, NULL);
00077 XML_SetUserData(m_Parser,this);
00078
00079 Reset();
00080 ResetRequirements();
00081 ResetLoadingHelpers();
00082
00083 m_psLoadData = &rsRawData;
00084
00085 bool result = XML_Parse(m_Parser,m_psLoadData->c_str(),m_psLoadData->size(),true);
00086
00087 if(!result)
00088 {
00089 std::string errorMsg(XML_ErrorString(XML_GetErrorCode(m_Parser)));
00090 std::string errorPos = Convert::ToStr(XML_GetCurrentLineNumber(m_Parser))+":"+Convert::ToStr(XML_GetCurrentColumnNumber(m_Parser));
00091 throwExceptionMacro("Expat error while parsing raw string. Error: "<<errorMsg<<"; Error position: "<<errorPos);
00092 }
00093
00094 XML_ParserFree(m_Parser);
00095
00096 FinalizeLoading();
00097
00098 CheckValidLoading();
00099
00100 ResetLoadingHelpers();
00101 };
00102
00103 std::string XMLStreamObject::SaveToString() const
00104 {
00105 return SaveToString(0);
00106 };
00107
00108 void
00109 XMLStreamObject::
00110 SaveToFile(const std::string& sFileName,
00111 const std::string& sXSLT,
00112 const std::string& sEncoding) const
00113 {
00114 std::ofstream file;
00115
00116 std::ios_base::openmode iOpenFlag = std::ios_base::out | std::ios_base::trunc;
00117 file.open(sFileName.c_str(), iOpenFlag );
00118
00119 if (!file.is_open()) throwExceptionMacro("Cannot open or create specified file to save. Filename: "<<sFileName);
00120
00121 try
00122 {
00123 if (!sEncoding.empty()) file <<"<?xml version=\"1.0\" encoding=\""<<sEncoding<<"\"?>\n";
00124 if (!sXSLT.empty()) file <<"<?xml-stylesheet type=\"text/xsl\" href=\""<<sXSLT<<"\"?>\n";
00125 file << this->SaveToString();
00126 file.close();
00127 }
00128 catchAllNPassMacro("Unknown error occured while saving setup. Please check error log for further information.");
00129 };
00130
00131 void
00132 XMLStreamObject::
00133 LoadFromFile(const std::string& sFileName)
00134 {
00135 std::ifstream file;
00136
00137 std::ios_base::openmode iOpenFlag = std::ios_base::in;
00138 file.open(sFileName.c_str(), iOpenFlag );
00139
00140 if (!file.is_open()) throwExceptionMacro("Cannot open or create specified file to load. Filename: " << sFileName);
00141
00142 try
00143 {
00144 std::streamsize filesize = itksys::SystemTools::FileLength(sFileName.c_str());
00145 char *buffer = new char [filesize];
00146
00147 file.read(buffer,filesize);
00148
00149 std::streamsize gsize = file.gcount();
00150
00151 std::string data(buffer,gsize);
00152
00153 delete[] buffer;
00154 file.close();
00155
00156 this->LoadFromString(data);
00157 }
00158 catchAllNPassMacro("Unknown error occured while loading setup. Please check error log for further information.");
00159 };
00160
00161 void
00162 XMLStreamObject::
00163 Reset()
00164 {
00165
00166 };
00167
00168 const std::string
00169 XMLStreamObject::
00170 GetXMLTag() const
00171 { return m_sXMLTag; };
00172
00173 void
00174 XMLStreamObject::
00175 CB_StartElement(const char * name,const char **pAttributes)
00176 {
00177 if (m_iActSubElementLevel==0)
00178 {
00179 if (name == GetXMLTag())
00180 {
00181 AttributesLoadProcessing(ConvertExpatAttrToMap(pAttributes));
00182 XML_SetCharacterDataHandler(m_Parser, &CB_Static_CharacterDataHandler);
00183 }
00184 else throwExceptionMacro("Wrong xml tag for used xml stream object class. Used Tag: " << name << ".Required Tag: " << this->GetXMLTag());
00185 }
00186 else if (m_iActSubElementLevel==1)
00187 {
00188 CommitSubElement();
00189 m_lContentStartPos = -1;
00190 m_lContentStopPos = -1;
00191 m_lElementStopPos = -1;
00192
00193
00194 m_sActSubElementTag = name;
00195 m_ActSubElementAttributes = ConvertExpatAttrToMap(pAttributes);
00196 m_lElementStartPos = XML_GetCurrentByteIndex(m_Parser);
00197
00198
00199 XML_SetCharacterDataHandler(m_Parser, &CB_Static_CharacterDataHandler);
00200 }
00201 else XML_SetCharacterDataHandler(m_Parser, NULL);
00202
00203 m_iActSubElementLevel++;
00204 };
00205
00206 void
00207 XMLStreamObject::
00208 CB_EndElement(const char *name)
00209 {
00210 m_iActSubElementLevel--;
00211
00212 if (m_iActSubElementLevel==1)
00213 {
00214 m_lContentStopPos = XML_GetCurrentByteIndex(m_Parser);
00215
00216
00217 XML_SetCharacterDataHandler(m_Parser, &CB_Static_CharacterDataHandler);
00218 }
00219 else if (m_iActSubElementLevel==0)
00220 {
00221 CommitSubElement();
00222 };
00223 };
00224
00225 void
00226 XMLStreamObject::
00227 CB_CharacterDataHandler(const char *inData, int inLength)
00228 {
00229 CommitSubElement();
00230 m_lContentStartPos = XML_GetCurrentByteIndex(m_Parser);
00231 m_lContentStopPos = -1;
00232 m_lElementStopPos = -1;
00233
00234
00235 XML_SetCharacterDataHandler(m_Parser, NULL);
00236 };
00237
00238 XMLStreamObject&
00239 XMLStreamObject::
00240 operator = (const XMLStreamObject& rXMLStreamObject)
00241 {
00242 m_sXMLTag = rXMLStreamObject.GetXMLTag();
00243
00244
00245
00246 return *this;
00247 };
00248
00249 XMLStreamObject::
00250 XMLStreamObject(const std::string& sXMLTag)
00251 {
00252 m_sXMLTag = sXMLTag;
00253 ResetLoadingHelpers();
00254 };
00255
00256 XMLStreamObject::
00257 XMLStreamObject(const XMLStreamObject& rXMLStreamObject)
00258 {
00259 ResetLoadingHelpers();
00260 *this = rXMLStreamObject;
00261 };
00262
00263 XMLStreamObject::
00264 ~XMLStreamObject()
00265 {
00266 ResetLoadingHelpers();
00267 };
00268
00269 void
00270 XMLStreamObject::
00271 SubElementLoadProcessing(const std::string& rsXMLSubTag, const std::string& rsXMLSubElement, const std::string& rsXMLSubData)
00272 {
00273 if (rsXMLSubTag!=cXML_Text) throwExceptionMacro("Unknown xml tag, unable to load value. Incorrect Tag: " << rsXMLSubTag);
00274
00275
00276
00277 };
00278
00279 void
00280 XMLStreamObject::
00281 AttributesLoadProcessing(const AttributesType& rAttributes)
00282 {
00283
00284
00285 };
00286
00287 void
00288 XMLStreamObject::
00289 SaveAttributes(AttributesSaveListType& rAttributes) const
00290 {
00291
00292 };
00293
00294 std::string
00295 XMLStreamObject::
00296 SaveData(const unsigned int& iDepth, bool& bHasSubElements) const
00297 {
00298 bHasSubElements = false;
00299 return "";
00300
00301 };
00302
00303 std::string
00304 XMLStreamObject::
00305 SaveToString(const unsigned int& iDepth) const
00306 {
00307 AttributesSaveListType attrs;
00308 std::string sAttrs = "";
00309
00310 try
00311 {
00312 SaveAttributes(attrs);
00313 }
00314 catchAllNPassMacro("Unkown error when saving attributes of tag. Tag: "+this->GetXMLTag());
00315
00316 bool bHasSubElements = true;
00317
00318 try
00319 {
00320 sAttrs = ConvertAttributesToString(attrs);
00321 }
00322 catchAllNPassMacro("Unkown error when converting attribute structure into save string. Tag: "+this->GetXMLTag());
00323
00324 std::string sElement = "";
00325 try
00326 {
00327 sElement = SaveData(iDepth, bHasSubElements);
00328 }
00329 catchAllNPassMacro("Unkown error when converting element data into save string. Tag: "+this->GetXMLTag());
00330
00331 std::string sResult = "<";
00332
00333 try
00334 {
00335 sResult += GetXMLTag();
00336 }
00337 catchAllNPassMacro("Unkown error when adding XML Tag. Tag: "+this->GetXMLTag());
00338
00339 try
00340 {
00341 AddIndentation(sResult, iDepth);
00342 }
00343 catchAllNPassMacro("Unkown error when adding indentation. Tag: "+this->GetXMLTag());
00344
00345 std::string sEndTag = "";
00346
00347 try
00348 {
00349 sEndTag = "</"+GetXMLTag()+">";
00350 if (bHasSubElements)
00351 {
00352 AddIndentation(sEndTag, iDepth);
00353 sEndTag = "\n"+sEndTag;
00354 }
00355 }
00356 catchAllNPassMacro("Unkown error when formatting end tag. Tag: "+this->GetXMLTag());
00357
00358 try
00359 {
00360 if (sAttrs.size()) sResult += " "+sAttrs;
00361 }
00362 catchAllNPassMacro("Unkown error when adding attr string. Tag: "+this->GetXMLTag());
00363
00364 try
00365 {
00366 if (sElement.size()) sResult += ">"+sElement+sEndTag;
00367 else sResult += " />";
00368 }
00369 catchAllNPassMacro("Unkown error when adding element string. Tag: "+this->GetXMLTag());
00370
00371 try
00372 {
00373 return sResult;
00374 }
00375 catchAllNPassMacro("Unkown error when returning result. Tag: "+this->GetXMLTag());
00376
00377 return "";
00378 };
00379
00380 std::string
00381 XMLStreamObject::
00382 CreateSimpleElement(const std::string& sTag, const std::string& sValue)
00383 {
00384 std::string sResult = "<"+sTag+">"+sValue+"</"+sTag+">";
00385 return sResult;
00386 };
00387
00388 void
00389 XMLStreamObject::
00390 AddSubElement(std::string& sData, const std::string& sTag, const std::string& sValue, const unsigned int& iParentalDepth)
00391 {
00392 try
00393 {
00394 std::string sResult = CreateSimpleElement(sTag,sValue);
00395 AddIndentation(sResult,iParentalDepth+1);
00396 sData += '\n'+sResult;
00397 }
00398 catchAllNPassStaticMacro("Unknown error while adding subelement to save string. Subelement tag: "+sTag+"; value: "+sValue+"; parental depth: "+Convert::ToStr(iParentalDepth));
00399 };
00400
00401 void
00402 XMLStreamObject::
00403 AddSubElement(std::string& sData, const std::string& sTag, const std::string& sValue, const AttributesType& rAttributes, const unsigned int& iParentalDepth)
00404 {
00405 try
00406 {
00407 std::string sAttr = "";
00408 for (AttributesType::const_iterator pos = rAttributes.begin(); pos != rAttributes.end(); pos++)
00409 {
00410 sAttr += " "+pos->first+"=\""+pos->second+"\"";
00411 }
00412 std::string sResult = "<"+sTag+sAttr+">"+sValue+"</"+sTag+">";
00413 AddIndentation(sResult,iParentalDepth+1);
00414 sData += '\n'+sResult;
00415 }
00416 catchAllNPassStaticMacro("Unknown error while adding subelement to save string. Subelement tag: "+sTag+"; value: "+sValue+"; parental depth: "+Convert::ToStr(iParentalDepth));
00417 };
00418
00419 void
00420 XMLStreamObject::
00421 AddSubElement(std::string& sData, const XMLStreamObject* pSubElement, const unsigned int& iParentalDepth)
00422 {
00423 std::string sTag = "NULL sub element";
00424 if (pSubElement)
00425 {
00426 sTag = pSubElement->GetXMLTag();
00427 std::string sResult = "";
00428 try
00429 {
00430 sResult = pSubElement->SaveToString(iParentalDepth+1);
00431 }
00432 catchAllNPassStaticMacro("Unknown error while generating subelement save string. Subelement tag: "+sTag+"; parental depth: "+Convert::ToStr(iParentalDepth));
00433 try
00434 {
00435 sData += "\n"+sResult;
00436 }
00437 catchAllNPassStaticMacro("Unknown error while adding subelement save string. Subelement tag: "+sTag+"; parental depth: "+Convert::ToStr(iParentalDepth)+"; sub element string: "+sResult);
00438 }
00439 else
00440 {
00441 std::string sLocation;
00442 GetStaticLocationMacro( sLocation );
00443 FREE::LogException("Warning", "Passed sub element was NULL.",sLocation);
00444 }
00445 };
00446
00447 void
00448 XMLStreamObject::
00449 AddSubElement(std::string& sData, const std::string& sSubElement, const unsigned int& iParentalDepth)
00450 {
00451 try
00452 {
00453 std::string sResult = sSubElement;
00454 AddIndentation(sResult,iParentalDepth+1);
00455 sData += '\n'+sResult;
00456 }
00457 catchAllNPassStaticMacro("Unknown error while adding subelement to save string. parental depth: "+Convert::ToStr(iParentalDepth)+"; subelement save string: "+sSubElement);
00458 };
00459
00460 void
00461 XMLStreamObject::
00462 AddIndentation(std::string& sData, const unsigned int& iDepth)
00463 {
00464 std::string sIndent;
00465 for (unsigned int i=0; i<iDepth; i++) sIndent+=" ";
00466 sData = sIndent+sData;
00467 };
00468
00469 bool
00470 XMLStreamObject::
00471 CheckValidLoading() const
00472 {
00473 if (m_NeededSubElements.size()>0)
00474 {
00475 std::string sMissing;
00476 STLStringVector::const_iterator pos;
00477
00478 for (pos = m_NeededSubElements.begin(); pos != m_NeededSubElements.end(); pos++)
00479 {
00480 sMissing += *pos + " ";
00481 };
00482 throwExceptionMacro("Loading of object was invalid, because required sub tags where missing. Please check xml file with schema definition. Missing tags: " << sMissing);
00483 }
00484 return true;
00485
00486 };
00487
00488 void
00489 XMLStreamObject::
00490 SetNeededSubElements()
00491 {
00492
00493
00494
00495 };
00496
00497 void
00498 XMLStreamObject::
00499 AddNeededSubElement(const std::string& sSubElementTag)
00500 {
00501 m_NeededSubElements.push_back(sSubElementTag);
00502 };
00503
00504 void
00505 XMLStreamObject::
00506 NotifyFoundSubElement(const std::string& sSubElementTag)
00507 {
00508 STLStringVector::iterator pos;
00509
00510 for (pos = m_NeededSubElements.begin(); pos != m_NeededSubElements.end(); pos++)
00511 {
00512 if ((*pos)==sSubElementTag)
00513 {
00514 m_NeededSubElements.erase(pos);
00515 return;
00516 }
00517 };
00518 };
00519
00520 void
00521 XMLStreamObject::
00522 ResetRequirements()
00523 {
00524 m_NeededSubElements.clear();
00525 SetNeededSubElements();
00526 };
00527
00528 void
00529 XMLStreamObject::
00530 ResetLoadingHelpers()
00531 {
00532 m_iActSubElementLevel = 0;
00533 m_sActSubElementTag.erase();
00534 m_ActSubElementAttributes.clear();
00535 m_psLoadData = NULL;
00536 m_lElementStartPos = -1;
00537 m_lElementStopPos = -1;
00538 m_lContentStartPos = -1;
00539 m_lContentStopPos = -1;
00540 };
00541
00542 XMLStreamObject::AttributesType
00543 XMLStreamObject::
00544 ConvertExpatAttrToMap(const char** pAttributes)
00545 {
00546 AttributesType attrs;
00547
00548 const char** pActAttr = pAttributes;
00549
00550 while (*pActAttr)
00551 {
00552 std::string sKey = *pActAttr;
00553 pActAttr++;
00554 std::string sValue = *pActAttr;
00555 pActAttr++;
00556 attrs.insert(AttributeType(sKey,sValue));
00557 };
00558
00559 return attrs;
00560 };
00561
00562 std::string
00563 XMLStreamObject::
00564 ExtractSubElementXmlString()
00565 {
00566 if (m_lElementStartPos==-1) return "";
00567
00568 if (m_lElementStartPos>m_lElementStopPos) return "";
00569
00570 return m_psLoadData->substr(m_lElementStartPos,m_lElementStopPos-m_lElementStartPos);
00571 };
00572
00573 std::string
00574 XMLStreamObject::
00575 ExtractSubElementContentString()
00576 {
00577 if (m_lContentStartPos==-1) return "";
00578
00579 if (m_lContentStartPos>m_lContentStopPos) return "";
00580
00581 return m_psLoadData->substr(m_lContentStartPos,m_lContentStopPos-m_lContentStartPos);
00582 };
00583
00584 void
00585 XMLStreamObject::
00586 CommitSubElement()
00587 {
00588 if (m_lContentStopPos>-1)
00589 {
00590 m_lElementStopPos = XML_GetCurrentByteIndex(m_Parser);
00591 SubElementLoadProcessing(m_sActSubElementTag,ExtractSubElementXmlString(),ExtractSubElementContentString());
00592 NotifyFoundSubElement(m_sActSubElementTag);
00593 }
00594 else if (m_lContentStartPos>-1)
00595 {
00596 m_lContentStopPos = XML_GetCurrentByteIndex(m_Parser);
00597 SubElementLoadProcessing(cXML_Text,ExtractSubElementContentString(),ExtractSubElementContentString());
00598 };
00599 };
00600
00601 std::string
00602 XMLStreamObject::
00603 ConvertAttributesToString(const AttributesSaveListType& rAttributes)
00604 {
00605 std::string sResult;
00606
00607 AttributesSaveListType::const_iterator pos;
00608
00609 for (pos = rAttributes.begin(); pos!= rAttributes.end(); pos++)
00610 {
00611 std::string sAttribut = pos->first + "=";
00612
00613 if (pos->second.find_first_of('"') == -1) sAttribut += "\""+pos->second+"\"";
00614 else if (pos->second.find_first_of('\'') == -1) sAttribut += "'"+pos->second+"'";
00615 else throwStaticExceptionMacro("Attribute value contains \" and '. Invalid value, cannot be saved as xml attribute. Invalid Value: " << pos->second);
00616
00617 sResult += sAttribut+" ";
00618 }
00619
00620 if (sResult.size()!=0) sResult.resize(sResult.size()-1);
00621
00622
00623 return sResult;
00624 };
00625
00626 }