00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <XML/XMLNode.h>
00022 #include <common/Defines.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <common/NumberParser.h>
00026
00027 void XMLNode::removeSpecialChars(const std::string &content, std::string &result)
00028 {
00029 result = "";
00030 for (char *c=(char *) content.c_str(); *c; c++)
00031 {
00032 char newchar = *c;
00033 if (*c == '\n') result += " ";
00034 else if (*c < 32 || *c > 126) result += " ";
00035 else if (*c == '>') result += ">";
00036 else if (*c == '<') result += "<";
00037 else if (*c == '\'') result += "'";
00038 else if (*c == '"') result += """;
00039 else if (*c == '&') result += "&";
00040 else if (*c == '%') result += "%";
00041 else result += *c;
00042 }
00043 }
00044
00045 void XMLNode::addSpecialChars(const std::string &content, std::string &result)
00046 {
00047 result = "";
00048 for (char *c=(char *) content.c_str(); *c; c++)
00049 {
00050 if (*c == '&')
00051 {
00052 if (strstr(c, ">") == c) { result += '>'; c+=3; }
00053 else if (strstr(c, "<") == c) { result += '<'; c+=3; }
00054 else if (strstr(c, "'") == c) { result += '\''; c+=5; }
00055 else if (strstr(c, """) == c) { result += '"'; c+=5; }
00056 else if (strstr(c, "&") == c) { result += '&'; c+=4; }
00057 else if (strstr(c, "&#") == c)
00058 {
00059 char *pos = strchr(c, ';');
00060 if (pos <= c + 3)
00061 {
00062 c+=2;
00063 result += S3D::formatStringBuffer("%c", atoi(c));
00064 *pos = '\0';
00065 c = pos + 1;
00066 }
00067 }
00068 else result += *c;
00069 }
00070 else result += *c;
00071 }
00072 }
00073
00074 const char *XMLNode::getSpacer(int space)
00075 {
00076 static std::string spacestr;
00077 spacestr = "";
00078
00079 for (int i=0; i<space; i++) spacestr+="\t";
00080 return spacestr.c_str();
00081 }
00082
00083 XMLNode::XMLNode(const char *name, const char *content, NodeType type) :
00084 name_(name), parent_(0), type_(type),
00085 useContentNodes_(false)
00086 {
00087 addContent(content, strlen(content));
00088 }
00089
00090 XMLNode::XMLNode(const char *name, const std::string &content, NodeType type) :
00091 name_(name), parent_(0), type_(type),
00092 useContentNodes_(false)
00093 {
00094 addContent(content.c_str(), content.size());
00095 }
00096
00097 XMLNode::XMLNode(const char *name, const LangString &langStringContent, NodeType type) :
00098 name_(name), parent_(0), type_(type),
00099 useContentNodes_(false)
00100 {
00101 std::string content;
00102 content = LangStringUtil::convertFromLang(langStringContent);
00103 addContent(content.c_str(), content.size());
00104 }
00105
00106 XMLNode::XMLNode(const char *name, float content, NodeType type) :
00107 name_(name), parent_(0), type_(type), useContentNodes_(false)
00108 {
00109 char buffer[20];
00110 snprintf(buffer, 20, "%.2f", content);
00111 addContent(buffer, strlen(buffer));
00112 }
00113
00114 XMLNode::XMLNode(const char *name, int content, NodeType type) :
00115 name_(name), parent_(0), type_(type), useContentNodes_(false)
00116 {
00117 char buffer[20];
00118 snprintf(buffer, 20, "%i", content);
00119 addContent(buffer, strlen(buffer));
00120 }
00121
00122 XMLNode::XMLNode(const char *name, unsigned int content, NodeType type) :
00123 name_(name), parent_(0), type_(type), useContentNodes_(false)
00124 {
00125 char buffer[20];
00126 snprintf(buffer, 20, "%u", content);
00127 addContent(buffer, strlen(buffer));
00128 }
00129
00130 XMLNode::XMLNode(const char *name, bool content, NodeType type) :
00131 name_(name), parent_(0), type_(type), useContentNodes_(false)
00132 {
00133 const char *buffer = content?"true":"false";
00134 addContent(buffer, strlen(buffer));
00135 }
00136
00137 XMLNode::XMLNode(const char *name, fixed content, NodeType type) :
00138 name_(name), parent_(0), type_(type), useContentNodes_(false)
00139 {
00140 const char *buffer = content.asString();
00141 addContent(buffer, strlen(buffer));
00142 }
00143
00144 XMLNode::XMLNode(const char *name, FixedVector &content, NodeType type) :
00145 name_(name), parent_(0), type_(type), useContentNodes_(false)
00146 {
00147 XMLNode *nodeA = new XMLNode("a");
00148 addChild(nodeA);
00149 XMLNode *nodeB = new XMLNode("b");
00150 addChild(nodeB);
00151 XMLNode *nodeC = new XMLNode("c");
00152 addChild(nodeC);
00153
00154 const char *buffer = content[0].asString();
00155 nodeA->addContent(buffer, strlen(buffer));
00156
00157 buffer = content[1].asString();
00158 nodeB->addContent(buffer, strlen(buffer));
00159
00160 buffer = content[2].asString();
00161 nodeC->addContent(buffer, strlen(buffer));
00162 }
00163
00164 XMLNode::XMLNode(const char *name, Vector &content, NodeType type) :
00165 name_(name), parent_(0), type_(type), useContentNodes_(false)
00166 {
00167 XMLNode *nodeA = new XMLNode("a");
00168 addChild(nodeA);
00169 XMLNode *nodeB = new XMLNode("b");
00170 addChild(nodeB);
00171 XMLNode *nodeC = new XMLNode("c");
00172 addChild(nodeC);
00173
00174 char buffer[20];
00175 snprintf(buffer, 20, "%.2f", content[0]);
00176 nodeA->addContent(buffer, strlen(buffer));
00177
00178 snprintf(buffer, 20, "%.2f", content[1]);
00179 nodeB->addContent(buffer, strlen(buffer));
00180
00181 snprintf(buffer, 20, "%.2f", content[2]);
00182 nodeC->addContent(buffer, strlen(buffer));
00183 }
00184
00185 XMLNode::~XMLNode()
00186 {
00187 while (!children_.empty())
00188 {
00189 XMLNode *node = children_.front();
00190 children_.pop_front();
00191 delete node;
00192 }
00193 while (!removedChildren_.empty())
00194 {
00195 XMLNode *node = removedChildren_.front();
00196 removedChildren_.pop_front();
00197 delete node;
00198 }
00199 while (!parameters_.empty())
00200 {
00201 XMLNode *node = parameters_.front();
00202 parameters_.pop_front();
00203 delete node;
00204 }
00205 while (!removedParameters_.empty())
00206 {
00207 XMLNode *node = removedParameters_.front();
00208 removedParameters_.pop_front();
00209 delete node;
00210 }
00211 }
00212
00213 bool XMLNode::writeToFile(const std::string &filename)
00214 {
00215 FileLines lines;
00216 addNodeToFile(lines, 0);
00217 return lines.writeFile(filename);
00218 }
00219
00220 void XMLNode::addNodeToFile(FileLines &lines, int spacing)
00221 {
00222 if (type_ == XMLNodeType)
00223 {
00224 std::string params;
00225 std::list<XMLNode *>::iterator pitor;
00226 for (pitor = parameters_.begin();
00227 pitor != parameters_.end();
00228 pitor++)
00229 {
00230 XMLNode *node = (*pitor);
00231 DIALOG_ASSERT(node->type_ == XMLParameterType);
00232
00233 std::string oldContent(node->getContent());
00234 std::string newContent;
00235 removeSpecialChars(oldContent, newContent);
00236
00237 params += " " + node->name_ + "='" + newContent + "'";
00238 }
00239
00240 if (children_.empty())
00241 {
00242 std::string oldContent(getContent());
00243 std::string newContent;
00244 removeSpecialChars(oldContent, newContent);
00245
00246 lines.addLine(S3D::formatStringBuffer("%s<%s%s>%s</%s>",
00247 getSpacer(spacing),
00248 name_.c_str(), params.c_str(),
00249 newContent.c_str(), name_.c_str()));
00250 }
00251 else
00252 {
00253 lines.addLine(S3D::formatStringBuffer("%s<%s%s>",
00254 getSpacer(spacing),
00255 name_.c_str(), params.c_str()));
00256
00257 std::list<XMLNode *>::iterator itor;
00258 for (itor = children_.begin();
00259 itor != children_.end();
00260 itor++)
00261 {
00262 XMLNode *node = (*itor);
00263 node->addNodeToFile(lines, spacing + 1);
00264 }
00265
00266 lines.addLine(S3D::formatStringBuffer("%s</%s>",
00267 getSpacer(spacing), name_.c_str()));
00268 }
00269 }
00270 else if (type_ == XMLCommentType)
00271 {
00272 lines.addLine(S3D::formatStringBuffer("%s<!-- %s -->",
00273 getSpacer(spacing), getContent()));
00274 }
00275 }
00276
00277 bool XMLNode::failChildren()
00278 {
00279 if (useContentNodes_)
00280 {
00281 std::list<XMLNode *>::iterator itor;
00282 for (itor = getChildren().begin();
00283 itor != getChildren().end();
00284 itor++)
00285 {
00286 XMLNode *node = (*itor);
00287 if (node->getType() == XMLNodeType)
00288 {
00289 node->returnError(S3D::formatStringBuffer("Unrecognised node."));
00290 return false;
00291 }
00292 }
00293 }
00294 else
00295 {
00296 if (!children_.empty())
00297 {
00298 XMLNode *node = children_.front();
00299 node->returnError(S3D::formatStringBuffer("Unrecognised node."));
00300 return false;
00301 }
00302 }
00303
00304 return true;
00305 }
00306
00307 bool XMLNode::failContent()
00308 {
00309 for (const char *c=getContent(); *c; c++)
00310 {
00311 if (*c != '\n' &&
00312 *c != '\r' &&
00313 *c != '\t' &&
00314 *c != ' ')
00315 {
00316 returnError(S3D::formatStringBuffer("Unexpected context : %s",
00317 getContent()));
00318 return false;
00319 }
00320 }
00321 return true;
00322 }
00323
00324 void XMLNode::resurrectRemovedChildren()
00325 {
00326 while (!removedChildren_.empty())
00327 {
00328 XMLNode *node = removedChildren_.front();
00329 removedChildren_.pop_front();
00330 children_.push_back(node);
00331
00332 node->resurrectRemovedChildren();
00333 }
00334 while (!removedParameters_.empty())
00335 {
00336 XMLNode *node = removedParameters_.front();
00337 removedParameters_.pop_front();
00338 parameters_.push_back(node);
00339 }
00340 }
00341
00342 bool XMLNode::getNamedChild(const char *name, XMLNode *&value,
00343 bool failOnError, bool remove)
00344 {
00345 std::list<XMLNode *>::iterator itor;
00346 for (itor = children_.begin();
00347 itor != children_.end();
00348 itor++)
00349 {
00350 XMLNode *node = (*itor);
00351 if (strcmp(name, node->getName()) == 0)
00352 {
00353 if (remove)
00354 {
00355 removedChildren_.push_back(node);
00356 children_.erase(itor);
00357 }
00358 value = node;
00359 return true;
00360 }
00361 }
00362
00363 if (failOnError)
00364 {
00365 returnError(S3D::formatStringBuffer("Failed to find \"%s\" node", name));
00366 }
00367 return false;
00368 }
00369
00370 bool XMLNode::getNamedParameter(const char *name, XMLNode *&value,
00371 bool failOnError, bool remove)
00372 {
00373 std::list<XMLNode *>::iterator itor;
00374 for (itor = parameters_.begin();
00375 itor != parameters_.end();
00376 itor++)
00377 {
00378 XMLNode *node = (*itor);
00379 if (strcmp(name, node->getName()) == 0)
00380 {
00381 if (remove)
00382 {
00383 removedParameters_.push_back(node);
00384 parameters_.erase(itor);
00385 }
00386 value = node;
00387 return true;
00388 }
00389 }
00390
00391 if (failOnError)
00392 {
00393 returnError(S3D::formatStringBuffer("Failed to find \"%s\" parameter", name));
00394 }
00395 return false;
00396 }
00397
00398 bool XMLNode::getNamedParameter(const char *name, std::string &value,
00399 bool failOnError, bool remove)
00400 {
00401 XMLNode *node;
00402 if (!getNamedParameter(name, node, failOnError, remove)) return false;
00403 value = node->getContent();
00404 return true;
00405 }
00406
00407 bool XMLNode::getNamedParameter(const char *name, LangString &value,
00408 bool failOnError, bool remove)
00409 {
00410 XMLNode *node;
00411 if (!getNamedParameter(name, node, failOnError, remove)) return false;
00412 value = LANG_STRING(node->getContent());
00413 return true;
00414 }
00415
00416 bool XMLNode::getNamedChild(const char *name, LangString &value,
00417 bool failOnError, bool remove)
00418 {
00419 XMLNode *node;
00420 if (!getNamedChild(name, node, failOnError, remove)) return false;
00421 value = LANG_STRING(node->getContent());
00422 return true;
00423 }
00424
00425 bool XMLNode::getNamedChild(const char *name, std::string &value,
00426 bool failOnError, bool remove)
00427 {
00428 XMLNode *node;
00429 if (!getNamedChild(name, node, failOnError, remove)) return false;
00430 value = node->getContent();
00431 return true;
00432 }
00433
00434 bool XMLNode::getNamedChild(const char *name, bool &value,
00435 bool failOnError, bool remove)
00436 {
00437 XMLNode *node;
00438 if (!getNamedChild(name, node, failOnError, remove)) return false;
00439
00440 if (0 == strcmp(node->getContent(), "true")) value = true;
00441 else if (0 == strcmp(node->getContent(), "false")) value = false;
00442 else
00443 {
00444 return node->returnError(
00445 "Failed to parse boolean value (should be true or false)");
00446 }
00447 return true;
00448 }
00449
00450 bool XMLNode::getNamedChild(const char *name, NumberParser &value,
00451 bool failOnError, bool remove)
00452 {
00453 XMLNode *node;
00454 if (!getNamedChild(name, node, failOnError, remove)) return false;
00455
00456 if (!value.setExpression(node->getContent()))
00457 return node->returnError("Failed to parse expression");
00458
00459 return true;
00460 }
00461
00462 bool XMLNode::getNamedChild(const char *name, float &value,
00463 bool failOnError, bool remove)
00464 {
00465 XMLNode *node;
00466 if (!getNamedChild(name, node, failOnError, remove)) return false;
00467
00468 if (sscanf(node->getContent(), "%f", &value) != 1)
00469 return node->returnError("Failed to parse float value");
00470 return true;
00471 }
00472
00473 bool XMLNode::getNamedChild(const char *name, int &value,
00474 bool failOnError, bool remove)
00475 {
00476 XMLNode *node;
00477 if (!getNamedChild(name, node, failOnError, remove)) return false;
00478
00479 if (sscanf(node->getContent(), "%i", &value) != 1)
00480 return node->returnError("Failed to parse int value");
00481 return true;
00482 }
00483
00484 bool XMLNode::getNamedChild(const char *name, unsigned int &value,
00485 bool failOnError, bool remove)
00486 {
00487 XMLNode *node;
00488 if (!getNamedChild(name, node, failOnError, remove)) return false;
00489
00490 if (sscanf(node->getContent(), "%u", &value) != 1)
00491 return node->returnError("Failed to parse unsigned int value");
00492 return true;
00493 }
00494
00495 bool XMLNode::getNamedChild(const char *name, fixed &value,
00496 bool failOnError, bool remove)
00497 {
00498 std::string v;
00499 if (!getNamedChild(name, v, failOnError, remove)) return false;
00500 value = fixed(v.c_str());
00501 return true;
00502 }
00503
00504 bool XMLNode::getNamedChild(const char *name, FixedVector &value,
00505 bool failOnError, bool remove)
00506 {
00507 XMLNode *node;
00508 if (!getNamedChild(name, node, failOnError, remove)) return false;
00509
00510 std::string a, b, c;
00511 if (!node->getNamedChild("A", a, false, true) &&
00512 !node->getNamedChild("a", a, false, true))
00513 {
00514 if (failOnError) node->returnError("Failed to find a node");
00515 return false;
00516 }
00517 if (!node->getNamedChild("B", b, false, true) &&
00518 !node->getNamedChild("b", b, false, true))
00519 {
00520 if (failOnError) node->returnError("Failed to find b node");
00521 return false;
00522 }
00523 if (!node->getNamedChild("C", c, false, true) &&
00524 !node->getNamedChild("c", c, false, true))
00525 {
00526 if (failOnError) node->returnError("Failed to find c node");
00527 return false;
00528 }
00529 if (failOnError && !node->failChildren()) return false;
00530
00531 value[0] = fixed(a.c_str());
00532 value[1] = fixed(b.c_str());
00533 value[2] = fixed(c.c_str());
00534 return true;
00535 }
00536
00537 bool XMLNode::getNamedChild(const char *name, Vector &value,
00538 bool failOnError, bool remove)
00539 {
00540 XMLNode *node;
00541 if (!getNamedChild(name, node, failOnError, remove)) return false;
00542
00543 Vector tmpValue;
00544 if (!node->getNamedChild("A", tmpValue[0], false, true) &&
00545 !node->getNamedChild("a", tmpValue[0], false, true))
00546 {
00547 if (failOnError) node->returnError("Failed to find a node");
00548 return false;
00549 }
00550 if (!node->getNamedChild("B", tmpValue[1], false, true) &&
00551 !node->getNamedChild("b", tmpValue[1], false, true))
00552 {
00553 if (failOnError) node->returnError("Failed to find b node");
00554 return false;
00555 }
00556 if (!node->getNamedChild("C", tmpValue[2], false, true) &&
00557 !node->getNamedChild("c", tmpValue[2], false, true))
00558 {
00559 if (failOnError) node->returnError("Failed to find c node");
00560 return false;
00561 }
00562 if (failOnError && !node->failChildren()) return false;
00563
00564 value = tmpValue;
00565 return true;
00566 }
00567
00568 const char *XMLNode::getContent()
00569 {
00570 if (useContentNodes_ &&
00571 getType() == XMLNodeType)
00572 {
00573 static std::string result;
00574
00575 result = "";
00576 std::list<XMLNode *>::iterator itor;
00577 for (itor = getChildren().begin();
00578 itor != getChildren().end();
00579 itor++)
00580 {
00581 XMLNode *node = (*itor);
00582 if (node->getType() == XMLContentType)
00583 {
00584 result += node->content_.c_str();
00585 }
00586 }
00587 return result.c_str();
00588 }
00589 else
00590 {
00591 return content_.c_str();
00592 }
00593 }
00594
00595 void XMLNode::setSource(const char *source)
00596 {
00597 source_ = source;
00598 }
00599
00600 void XMLNode::setLine(int line, int col)
00601 {
00602 line_ = line;
00603 col_ = col;
00604 }
00605
00606 void XMLNode::addChild(XMLNode *node)
00607 {
00608 children_.push_back(node);
00609 node->setUseContentNodes(useContentNodes_);
00610 node->parent_ = this;
00611 node->source_ = source_;
00612 }
00613
00614 void XMLNode::addParameter(XMLNode *node)
00615 {
00616 parameters_.push_back(node);
00617 node->parent_ = this;
00618 node->source_ = source_;
00619 }
00620
00621 void XMLNode::addContent(const char *data, int len)
00622 {
00623 std::string oldContent, newContent;
00624 oldContent.append(data, len);
00625 addSpecialChars(oldContent, newContent);
00626
00627 if (useContentNodes_)
00628 {
00629 XMLNode *newNode =
00630 new XMLNode("__TEXT__", "", XMLNode::XMLContentType);
00631 newNode->setLine(line_, col_);
00632 newNode->content_.append(newContent);
00633 addChild(newNode);
00634 }
00635 else
00636 {
00637 content_.append(newContent);
00638 }
00639 }
00640
00641 bool XMLNode::returnError(const std::string &error)
00642 {
00643 S3D::dialogMessage("XMLNode",
00644 S3D::formatStringBuffer("Parse Error, File:%s Line:%i Col:%i Node:%s Error:%s",
00645 source_.c_str(), line_, col_, getName(), error.c_str()));
00646 return false;
00647 }