00001 #include "CSXMLHelper.h"
00002
00003 #ifdef WIN32
00004 #pragma warning(disable : 4786 )
00005 #endif
00006
00007 #ifdef USE_TINYXML
00008
00009 #include <vector>
00010
00011 const char *CSXMLHelper::CLASS = "CSXMLHelper";
00012
00013 void cstoupper(char * s)
00014 {
00015 int i = strlen(s);
00016 for (int e =0; e < i; e++)
00017 {
00018 s[e] = toupper(s[e]);
00019 }
00020 }
00021
00022 void CSXMLHelper::addEntitiesFromFile(const std::string &filename, const std::string &parentFilename)
00023 {
00024 static char *functionName="addEntitiesFromFile";
00025 LOG_ENTER
00026 std::string fullName;
00027
00028
00029
00030 int posStart = parentFilename.find_last_of("\\", parentFilename.size());
00031 if (posStart != -1)
00032 {
00033 fullName = parentFilename.substr(0, posStart+1);
00034 }
00035 fullName += filename;
00036
00037
00038
00039
00040 FILE *handle = fopen(fullName.c_str(), "rt");
00041 if (handle == 0)
00042 {
00043 LOG_DEBUG_MESSAGE(((std::string)"Entity file: \"") + fullName+"\" cannot be opened!")
00044 LOG_EXIT
00045 return;
00046 }
00047 static char tmp[1024];
00048
00049
00050
00051
00052 while (1)
00053 {
00054 char *res = fgets(tmp, 1024, handle);
00055 std::string strValue = tmp;
00056 if (res == 0)
00057 {
00058 break;
00059 }
00060 if (strstr(tmp, "<!") != 0)
00061 {
00062 if (strstr(tmp, "SYSTEM") != 0)
00063 {
00064
00065 int posStart = strValue.find_first_of('\"');
00066 int posEnd = strValue.find_first_of('\"', posStart+1);
00067 std::string dtdName = strValue.substr(posStart+1, (posEnd-1) - (posStart));
00068 if (parentFilename.size() != 0)
00069 {
00070 addEntitiesFromFile(dtdName, parentFilename);
00071 }
00072 else
00073 {
00074 addEntitiesFromFile(dtdName, filename);
00075 }
00076 }
00077 else
00078 {
00079 if (strstr(tmp, "!ENTITY") != 0)
00080 {
00081 int posStart = strValue.find_first_of("!ENTITY");
00082 posStart = strValue.find_first_of(" \t", posStart);
00083 posStart = strValue.find_first_not_of(" \t", posStart);
00084 int posEnd = strValue.find_first_of(" \t", posStart);
00085 std::string key = strValue.substr(posStart, posEnd - posStart);
00086 key = "&" + key + ";";
00087
00088 posStart = strValue.find_first_of('\"');
00089 posEnd = strValue.find_first_of('\"', posStart+1);
00090
00091 std::string value = strValue.substr(posStart+1, (posEnd-1) - (posStart));
00092 mEntityMap.insert(EntityMap::value_type(key, value));
00093 }
00094 }
00095 }
00096 }
00097
00098 fclose(handle);
00099 LOG_EXIT
00100 }
00101
00102
00103 CSXMLHelper::CSXMLHelper(const std::string &xmlFilename, const std::string &contextNode)
00104 {
00105 static char *functionName="CSXMLHelper";
00106 mError = CSXML_OK;
00107 mXMLdoc = 0;
00108
00109 mXMLdoc = new TiXmlDocument(xmlFilename);
00110 mXMLdoc->setIgnoreNoEndTag(false);
00111 mXMLdoc->SetCondenseWhiteSpace(true);
00112
00113 if (!mXMLdoc)
00114 {
00115 mError = CSXML_CONTEXT_LOADING_ERROR;
00116 std::string errorMessageString;
00117 errorMessageString = std::string("Error - while loading context \"" + contextNode +"\"!");
00118 mErrorMessageString = mErrorMessageString + "\n"+ errorMessageString;
00119 }
00120
00121 addEntitiesFromFile(xmlFilename, "");
00122
00123 if (!mXMLdoc->LoadFile() )
00124 {
00125 mError = CSXML_DOCUMENT_LOADING_ERROR;
00126 std::string errorMessageString;
00127 errorMessageString = std::string("Error - while loading document \"" + xmlFilename +"\"!");
00128 mErrorMessageString = mErrorMessageString + "\n"+ errorMessageString;
00129 return;
00130 }
00131 mXMLsource = mXMLdoc->FirstChildElement(contextNode);
00132 }
00133
00134 CSXMLHelper::~CSXMLHelper()
00135 {
00136 static char *functionName="~CSXMLHelper";
00137 LOG_ENTER
00138 delete (mXMLdoc);
00139 mXMLdoc = 0;
00140 mXMLsource = 0;
00141 mEntityMap.clear();
00142 LOG_EXIT
00143 }
00144
00145 int CSXMLHelper::getInt(const std::string &xpath)
00146 {
00147 static char *functionName="getInt";
00148 LOG_ENTER
00149 int ret = 0;
00150 if (mError != 0)
00151 {
00152 LOG_WARN_MESSAGE("Error")
00153 LOG_EXIT
00154 throw "error";
00155 }
00156 try
00157 {
00158 TiXmlNode *node = getXPathResult(xpath);
00159 if (node == 0)
00160 {
00161 LOG_EXIT
00162 return 0;
00163 }
00164 if (node->Type() == TiXmlNode::FUNCTION)
00165 {
00166 ret = toInt(*node);
00167 delete node;
00168 node = 0;
00169 }
00170 else
00171 {
00172 TiXmlText *element = node->ToText();
00173 if (element == 0)
00174 {
00175 LOG_DEBUG_MESSAGE("XPath \"" + xpath + "\" doesn't represent a text element!")
00176 }
00177 ret = toInt(*element);
00178 }
00179 }
00180 catch(...)
00181 {
00182 mError = CSXML_XPATH_ERROR;
00183 std::string errorMessageString;
00184 errorMessageString = "tinyXMLException";
00185 mErrorMessageString = mErrorMessageString + "\n"+ errorMessageString;
00186 LOG_WARN_MESSAGE(mErrorMessageString)
00187 LOG_EXIT
00188 throw "error";
00189 }
00190 LOG_EXIT
00191 return ret;
00192 }
00193
00194 std::string CSXMLHelper::getString(const std::string &xpath)
00195 {
00196 static char *functionName="getString";
00197 LOG_ENTER
00198 std::string cstr;
00199 if (mError != 0)
00200 {
00201 LOG_WARN_MESSAGE("XML! Not properly initialized!")
00202 LOG_EXIT
00203 throw std::string("XML! Not properly initialized!");
00204 }
00205 try
00206 {
00207 TiXmlNode *node = getXPathResult(xpath);
00208 if (node == 0)
00209 {
00210 LOG_EXIT
00211 return "";
00212 }
00213 if (node->Type() == TiXmlNode::FUNCTION)
00214 {
00215 cstr = toAscii(*node);
00216 delete node;
00217 node = 0;
00218 }
00219 else
00220 {
00221 TiXmlText *element = node->ToText();
00222 if (element == 0)
00223 {
00224 LOG_DEBUG_MESSAGE("XPath \"" + xpath + "\" doesn't represent a text element!")
00225 }
00226 cstr = toAscii(*element);
00227 }
00228
00229 }
00230 catch(...)
00231 {
00232 mError = CSXML_XPATH_ERROR;
00233 std::string errorMessageString;
00234 errorMessageString = "tinyXMLException";
00235 mErrorMessageString = mErrorMessageString + "\n"+ errorMessageString;
00236 LOG_WARN_MESSAGE(mErrorMessageString)
00237 LOG_EXIT
00238 throw "error";
00239 }
00240 LOG_EXIT
00241 return cstr;
00242 }
00243
00244 ElementDescription CSXMLHelper::getElementDescription(std::string &xpath)
00245 {
00246 static char *functionName="getElementDescription";
00247 LOG_ENTER
00248 ElementDescription desc;
00249 int posStart;
00250 int posEnd;
00251 LOG_DEBUG_MESSAGE("current xpath: "+ xpath)
00252
00253
00254
00255
00256 const std::string FKT_COUNT = "count(";
00257 if (xpath.compare(0, FKT_COUNT.size(), FKT_COUNT) == 0)
00258 {
00259 LOG_DEBUG_MESSAGE("Function count() encountered: ")
00260
00261
00262 xpath = xpath.substr(FKT_COUNT.size(), xpath.size() - FKT_COUNT.size()-1);
00263 desc.count = true;
00264 desc.function = true;
00265 }
00266
00267
00268
00269
00270 posStart = xpath.find_first_of("/");
00271 if (posStart == 0)
00272 {
00273
00274 desc.leadingSlash = true;
00275 posStart = 1;
00276 }
00277 else
00278 {
00279
00280 posStart = 0;
00281 }
00282
00283
00284
00285
00286
00287 posEnd = xpath.find_first_of("/", posStart);
00288 if (posEnd == -1)
00289 {
00290
00291 posEnd = xpath.size();
00292 }
00293
00294 desc.elementName = xpath.substr(posStart, posEnd - posStart);
00295 LOG_DEBUG_MESSAGE("path element name: "+ desc.elementName)
00296
00297
00298
00299 if (xpath.size() - posEnd > 0)
00300 {
00301 xpath = xpath.substr(posEnd, xpath.size() - posEnd);
00302
00303
00304 posStart = xpath.find_first_of("/");
00305 if (posStart == 0)
00306 {
00307 if (xpath.size() - 1 > 0)
00308 {
00309 xpath = xpath.substr(1, xpath.size() - 1);
00310 }
00311 else
00312 {
00313
00314 xpath = "";
00315 }
00316 }
00317 }
00318 else
00319 {
00320
00321 xpath = "";
00322 }
00323
00324
00325
00326
00327 posStart = desc.elementName.find_first_of("[", posStart);
00328 if (posStart != -1)
00329 {
00330
00331
00332 std::string predicateValue = desc.elementName.substr(posStart+1, desc.elementName.size() - (posStart+1+1));
00333 desc.elementName = desc.elementName.substr(0, posStart);
00334 desc.predicatePos = atoi(predicateValue.c_str()) - 1;
00335 }
00336
00337 LOG_DEBUG_MESSAGE("next xpath: "+ xpath)
00338 LOG_EXIT
00339 return desc;
00340 }
00341
00342 TiXmlNode *CSXMLHelper::getNextNode(TiXmlNode *sourceElement, std::string &xpath)
00343 {
00344 static char *functionName="getNextNode";
00345 LOG_ENTER
00346 TiXmlNode *result = sourceElement;
00347
00348
00349
00350
00351 if (xpath.size() == 0)
00352 {
00353 LOG_EXIT
00354 return result;
00355 }
00356
00357
00358
00359
00360 ElementDescription elementDescription = getElementDescription(xpath);
00361
00362
00363
00364
00365 if (elementDescription.leadingSlash)
00366 {
00367 sourceElement = mXMLdoc;
00368 }
00369
00370
00371
00372
00373 TiXmlNode *nextSourceElement = sourceElement->FirstChildElement(elementDescription.elementName);
00374 if (nextSourceElement == 0)
00375 {
00376 LOG_EXIT
00377 return 0;
00378 }
00379
00380
00381
00382
00383 if (elementDescription.predicatePos != -1)
00384 {
00385 LOG_DEBUG_MESSAGE("Predicate encountered!")
00386 std::string name = nextSourceElement->Value();
00387 int count = 0;
00388 char tmp[10];
00389 sprintf(tmp,"%i", elementDescription.predicatePos + 1);
00390 while ((nextSourceElement != 0) && (count != elementDescription.predicatePos))
00391 {
00392 nextSourceElement = nextSourceElement->NextSibling(name);
00393 if (nextSourceElement)
00394 {
00395 count++;
00396 }
00397 }
00398 if (result == 0)
00399 {
00400 LOG_DEBUG_MESSAGE(name+"["+tmp+"] not found!")
00401 LOG_EXIT
00402 return 0;
00403 }
00404 else
00405 {
00406 LOG_DEBUG_MESSAGE(name+"["+tmp+"] found!")
00407 }
00408 }
00409
00410 result = getNextNode(nextSourceElement, xpath);
00411 if (result == 0)
00412 {
00413 LOG_EXIT
00414 return 0;
00415 }
00416 std::string name = result->Value();
00417
00418
00419
00420
00421 if (elementDescription.function)
00422 {
00423 if (elementDescription.count)
00424 {
00425 char tmp[10];
00426 int count = 1;
00427 LOG_DEBUG_MESSAGE(((std::string)"Counting Node: ")+ result->Value())
00428
00429 while (result != 0)
00430 {
00431 result = result->NextSibling(name);
00432 if (result)
00433 {
00434 count++;
00435 }
00436 }
00437 sprintf(tmp,"%i", count);
00438 LOG_DEBUG_MESSAGE(name +" found "+ tmp +" times.")
00439
00440 TiFunctionReturn *ret = new TiFunctionReturn(tmp);
00441 result = ret;
00442
00443 }
00444 }
00445
00446 LOG_EXIT
00447 return result;
00448 }
00449
00450 TiXmlNode *CSXMLHelper::getXPathResult(const std::string &xpath)
00451 {
00452 static char *functionName="getXPathResult";
00453 static char h[1025];
00454 LOG_ENTER
00455 h[0] = 0;
00456 strcat(h, "normalize-space(");
00457 strcat(h, xpath.c_str());
00458 strcat(h, ")");
00459
00460
00461
00462 std::string path = xpath;
00463
00464 TiXmlNode *result = 0;
00465 result = getNextNode(mXMLsource, path);
00466 if (result==0)
00467 {
00468
00469 if (!xpath.find("count"))
00470 {
00471 LOG_DEBUG_MESSAGE(xpath + "->0" )
00472 }
00473 else
00474 {
00475 LOG_DEBUG_MESSAGE(xpath + "->" )
00476 }
00477 LOG_EXIT
00478 return 0;
00479 }
00480
00481 if (!result->NoChildren())
00482 {
00483 result = result->FirstChild();
00484 }
00485 LOG_DEBUG_MESSAGE(xpath + "->" + lookUp(result->Value()) )
00486
00487 LOG_EXIT
00488 return result;
00489 }
00490
00491 int CSXMLHelper::getError(void)
00492 {
00493 return mError;
00494 }
00495
00496 std::string CSXMLHelper::getErrorMessage(void)
00497 {
00498 return mErrorMessageString;
00499 }
00500
00501 std::string CSXMLHelper::toAscii(const TiXmlNode &node)
00502 {
00503 static char *functionName="toAscii";
00504 return lookUp(node.Value());
00505 }
00506
00507 int CSXMLHelper::toInt(const TiXmlNode &node)
00508 {
00509 static char *functionName="toInt";
00510 std::string value = node.Value();
00511 int result;
00512 result = atoi(lookUp(value).c_str());
00513
00514 return result;
00515 }
00516
00517 std::string replace(const std::string &key, const std::string &predicate, const std::string &value);
00518
00519
00520 std::string CSXMLHelper::lookUp(const std::string &key)
00521 {
00522 static char *functionName="lookUp";
00523 LOG_ENTER
00524 std::string newKey = key;
00525 std::string p = findPredicate(key);
00526 if (p.size() == 0)
00527 {
00528 LOG_EXIT
00529 return newKey;
00530 }
00531
00532 do
00533 {
00534 std::string value;
00535 EntityMap::iterator iter = mEntityMap.find(p);
00536 if (iter != mEntityMap.end())
00537 {
00538 value = iter->second;
00539 }
00540 newKey = replace(newKey, p, value);
00541 p = findPredicate(newKey);
00542 } while (p.size() > 0);
00543
00544 LOG_EXIT
00545 return newKey;
00546 }
00547
00548 std::string CSXMLHelper::findPredicate(const std::string &key)
00549 {
00550 EntityMap::iterator iter = mEntityMap.begin();
00551 while (iter != mEntityMap.end())
00552 {
00553 if (strstr(key.c_str(), iter->first.c_str()))
00554 {
00555 return iter->first;
00556 }
00557 iter++;
00558 }
00559 return "";
00560 }
00561
00562
00563 std::string replace(const std::string &key, const std::string &predicate, const std::string &value)
00564 {
00565 std::string newKey;
00566 std::string rest;
00567 int posStart = strstr(key.c_str(), predicate.c_str()) - key.c_str();
00568 int len = predicate.size();
00569 if (posStart != 0)
00570 {
00571 newKey = key.substr(0, posStart);
00572 }
00573 else
00574 {
00575 newKey = key.substr(len, key.size()-len);
00576 }
00577 newKey = newKey +value;
00578
00579 if (posStart+len < key.size())
00580 {
00581 newKey = newKey + key.substr(posStart + len, key.size() - (posStart + len) );
00582 }
00583
00584 return newKey;
00585 }
00586
00587 #endif // USE_TINYXML