00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "XMLNode.h"
00026
00027 namespace cmlabs {
00028
00029
00030
00031
00032
00033 XMLNode::XMLNode()
00034 {
00035 isXMLUTF = false;
00036 lineno = charno = 0;
00037
00038 attributes = NULL;
00039 childTags = NULL;
00040 }
00041
00042 XMLNode::XMLNode(const JString& s)
00043 {
00044 isXMLUTF = false;
00045 lineno = charno = 0;
00046 setTag(s);
00047
00048 attributes = NULL;
00049 childTags = NULL;
00050 }
00051
00052 XMLNode::~XMLNode()
00053 {
00054 delete childTags;
00055 delete attributes;
00056 }
00057
00058 Object* XMLNode::clone() const {
00059 XMLNode* xn = new XMLNode();
00060 xn->isXMLUTF = isXMLUTF;
00061 xn->parent = NULL;
00062 xn->tag = tag;
00063 xn->text = text;
00064 if (attributes != NULL) {
00065 xn->attributes = new Dictionary();
00066 xn->attributes->copyAll(attributes);
00067 }
00068 if (childTags != NULL) {
00069 xn->childTags = new ObjectCollection();
00070 xn->childTags->copyAll(childTags);
00071 }
00072 xn->lineno = lineno;
00073 xn->charno = charno;
00074 return (Object*) xn;
00075 }
00076
00077
00078 void XMLNode::deleteAllChildNodes() {
00079
00080 if ( (childTags == NULL) || (childTags->getCount() == 0) )
00081 return;
00082
00083 XMLNode* node;
00084
00085 while ( (node = (XMLNode*) childTags->getFirst() ) != NULL) {
00086 node->deleteAllChildNodes();
00087
00088 childTags->removeFirst();
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 }
00101
00102 bool XMLNode::isUTF() {
00103 return isXMLUTF;
00104 }
00105
00106 JString XMLNode::getTag() const
00107 {
00108 return tag;
00109 }
00110
00111 void XMLNode::setTag(const JString& t)
00112 {
00113 tag = t;
00114
00115 }
00116
00117
00118 JString XMLNode::getText() const
00119 {
00120 return text;
00121 }
00122
00123 void XMLNode::setText(const JString& t)
00124 {
00125 text = t;
00126 }
00127
00128 JString XMLNode::getTextContent()
00129 {
00130 JString str = this->asXMLChildrenOnly();
00131 if (str.length() > 0)
00132 return str;
00133 else
00134 return text;
00135 }
00136
00137 void XMLNode::addAttribute(const JString& attr, const JString& attrValue) {
00138 if (attributes == NULL)
00139 attributes = new Dictionary();
00140
00141 attributes->put(attr,attrValue);
00142 }
00143
00144
00145 void XMLNode::addChildTag(Object* childValue) {
00146 if (childTags == NULL)
00147 childTags = new ObjectCollection();
00148 childTags->addLast(childValue);
00149 }
00150
00151 JString XMLNode::indent(int nestLevel) {
00152 JString i;
00153 for (int j = 0; j < nestLevel; j++){
00154 i += "\t";
00155 }
00156 return(i);
00157 }
00158
00159 bool XMLNode::isEmpty() const {
00160
00161
00162 return ((lineno == 0) || (tag.length() == 0));
00163 }
00164
00165 JString XMLNode::toHTML() {
00166
00167
00168 JString preText;
00169 JString postText;
00170 if (isDirectiveNode()) {
00171 if (directive.contains("\n"))
00172 preText += JString::format("<font class=\"xmldir\"><?<br>\n%s<br>?></font><br>\n", (char*) directive.toHTML().indentHTML());
00173 else
00174 preText += JString::format("<font class=\"xmldirective\"><? %s ?></font><br>\n", (char*) directive.toHTML());
00175 }
00176
00177 if (preComment.length() > 0)
00178 if (preComment.contains("\n"))
00179 preText += JString::format("<font class=\"xmlcomment\"><!--<br>\n%s<br>--><br></font>\n", (char*) preComment.toHTML().indentHTML());
00180 else
00181 preText += JString::format("<font class=\"xmlcomment\"><!-- %s --></font><br>\n", (char*) preComment.toHTML());
00182 if (postComment.length() > 0)
00183 if (postComment.contains("\n"))
00184 postText += JString::format("<font class=\"xmlcomment\"><!--<br>\n%s<br>--><br></font>\n", (char*) postComment.toHTML().indentHTML());
00185 else
00186 postText += JString::format("<font class=\"xmlcomment\"><!-- %s --></font><br>\n", (char*) postComment.toHTML());
00187
00188 JString key, value;
00189 JString paramXML;
00190 if (attributes != NULL) {
00191 for (int n=0; n<attributes->getCount(); n++) {
00192 if ( (key = attributes->getKey(n)).length() > 0 ) {
00193 value = attributes->get(n);
00194 paramXML += JString::format(" <font class=\"xmlparam\">%s</font>=<font class=\"xmlvalue\">\"%s\"</font>", (char*) key, (char*) value);
00195 }
00196 }
00197 }
00198
00199 if ((text.length() == 0) && ( (childTags == NULL) || (childTags->getCount() == 0)) ) {
00200 return JString::format("%s<font class=\"xmlmain\"><<font class=\"xmltag\">%s</font>%s /><br></font>\n%s",
00201 (char*) preText, (char*) tag, (char*) paramXML, (char*) postText);
00202 }
00203
00204 JString xml;
00205 if (childTags != NULL) {
00206 for (XMLNode* node = (XMLNode*) childTags->getFirst(); node != NULL; node = (XMLNode*) childTags->getNext())
00207 xml += node->toHTML().indentHTML();
00208 }
00209
00210 if ( (xml.length() == 0) && (text.length() > 0) ) {
00211 xml += text.splitLinesOnWidth(70).printListLine("\n").toHTML();
00212 if (xml.contains("\n")) {
00213 return JString::format("%s<font class=\"xmlmain\"><<font class=\"xmltag\">%s</font>%s><br>\n%s</<font class=\"xmltag\">%s</font>><br></font>\n%s",
00214 (char*) preText, (char*) tag, (char*) paramXML, (char*) xml.indentHTML(), (char*) tag, (char*) postText);
00215 }
00216 else
00217 return JString::format("%s<font class=\"xmlmain\"><<font class=\"xmltag\">%s</font>%s>%s</<font class=\"xmltag\">%s</font>><br></font>\n%s",
00218 (char*) preText, (char*) tag, (char*) paramXML, (char*) xml, (char*) tag, (char*) postText);
00219 }
00220
00221 return JString::format("%s<font class=\"xmlmain\"><<font class=\"xmltag\">%s</font>%s><br>\n%s</<font class=\"xmltag\">%s</font>><br></font>\n%s",
00222 (char*) preText, (char*) tag, (char*) paramXML, (char*) xml, (char*) tag, (char*) postText);
00223 }
00224
00225
00226 JString XMLNode::asXML(int nestLevel, bool withCRs) {
00227
00228
00229
00230
00231 JString preText;
00232 JString postText;
00233 if ( isXMLUTF && (this->parent == NULL)) {
00234 preText = preText.addUTFHeader();
00235 }
00236 if (isDirectiveNode()) {
00237 if (directive.contains("\n"))
00238 preText += JString::format("<?\n%s?>\n", (char*) directive.indentXML());
00239 else
00240 preText += JString::format("<?%s?>\n", (char*) directive);
00241 }
00242
00243 if (preComment.length() > 0)
00244 if (preComment.contains("\n"))
00245 preText += JString::format("<!--\n%s-->\n", (char*) preComment.indentXML());
00246 else
00247 preText += JString::format("<!-- %s -->\n", (char*) preComment);
00248 if (postComment.length() > 0)
00249 if (postComment.contains("\n"))
00250 postText += JString::format("<!--\n%s-->\n", (char*) postComment.indentXML());
00251 else
00252 postText += JString::format("<!-- %s -->\n", (char*) postComment);
00253
00254 if (tag.length() == 0)
00255 return (preText + text.splitLinesOnWidth(70).printListLine("\n") + postText).indentXML();
00256
00257 JString paramXML;
00258 if (attributes != NULL) {
00259 for (int n=0; n<attributes->getCount(); n++) {
00260 paramXML += JString::format(" %s=\"%s\"", (char*) attributes->getKey(n).xmlStringEncode(), (char*) attributes->get(n).xmlStringEncode());
00261 }
00262 }
00263 if ((text.length() == 0) && ( (childTags == NULL) || (childTags->getCount() == 0) ) ) {
00264 return JString::format("%s<%s%s />\n%s", (char*) preText, (char*) tag, (char*) paramXML, (char*) postText);
00265 }
00266
00267 JString xml;
00268 if (childTags != NULL) {
00269 for (XMLNode* node = (XMLNode*) childTags->getFirst(); node != NULL; node = (XMLNode*) childTags->getNext())
00270 xml += node->asXML(nestLevel + 1, withCRs).indentXML();
00271 }
00272
00273 if ( (xml.length() == 0) && (text.length() > 0) ) {
00274 if (isXMLUTF)
00275 xml += text.splitLinesOnWidth(70).printListLine("\n");
00276 else {
00277
00278 if (!text.contains("\n"))
00279 xml += text.xmlStringEncode();
00280 else {
00281 Collection lines = text.splitLinesOnWidth(70);
00282 xml += lines.get(0).xmlStringEncode();
00283 for (int l=1; l<lines.getCount(); l++) {
00284 xml += JString("\n") + lines.get(l).xmlStringEncode();
00285 }
00286 }
00287 }
00288 if (xml.contains("\n")) {
00289 return JString::format("%s<%s%s>\n%s</%s>\n%s", (char*) preText, (char*) tag, (char*) paramXML, (char*) xml.indentXML(), (char*) tag, (char*) postText);
00290 }
00291 else
00292 return JString::format("%s<%s%s>%s</%s>%s\n", (char*) preText, (char*) tag, (char*) paramXML, (char*) xml, (char*) tag, (char*) postText);
00293 }
00294
00295 return JString::format("%s<%s%s>\n%s</%s>\n%s", (char*) preText, (char*) tag, (char*) paramXML, (char*) xml, (char*) tag, (char*) postText);
00296 }
00297
00298 JString XMLNode::asXMLChildrenOnly() {
00299
00300 if (childTags == NULL)
00301 return "";
00302
00303 JString xml;
00304 XMLNode* node;
00305
00306
00307
00308
00309
00310 for ( Object* c = childTags->getFirst();
00311 c != (Object *) NULL;
00312 c = childTags->getNext()) {
00313 node = (XMLNode *) c;
00314 xml += node->asXML(0, true);
00315 }
00316 return xml;
00317 }
00318
00319
00320 JString XMLNode::asXML() {
00321 return (asXML(0, true));
00322 }
00323
00324 JString XMLNode::toXML() {
00325 return (asXML(0, true));
00326 }
00327
00328 JString XMLNode::toXMLChildrenOnly() {
00329 return asXMLChildrenOnly();
00330 }
00331
00332 JString XMLNode::asXMLWithCRs()
00333 {
00334 return (asXML(0, true));
00335 }
00336
00337 Dictionary* XMLNode::getAttributes()
00338 {
00339 return attributes;
00340 }
00341
00342 bool XMLNode::hasAttribute(const JString& attr) const {
00343 if (attributes == NULL)
00344 return false;
00345 return (attributes->containsIgnoreCase(attr));
00346 }
00347
00348 JString XMLNode::getAttribute(const JString& attr) const {
00349 if (attributes == NULL)
00350 return "";
00351 return (attributes->getIgnoreCase(attr));
00352 }
00353
00354 ObjectCollection* XMLNode::getChildTags()
00355 {
00356 return childTags;
00357 }
00358
00359 XMLNode* XMLNode::getFirstChildNode() {
00360 if (childTags == NULL)
00361 return NULL;
00362 return (XMLNode*) childTags->get(0);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 JString XMLNode::findAttr(const JString& attr) const
00376 {
00377 if (attributes == NULL)
00378 return "";
00379 return (attributes->getIgnoreCase(attr));
00380
00381
00382
00383 }
00384
00385 XMLNode* XMLNode::getChildNode(Collection& childPath)
00386 {
00387
00388 XMLNode* node = this;
00389 for (int i = 0; i < childPath.getCount(); i++) {
00390 node = node->getChildNode(childPath.get(i));
00391 }
00392 return node;
00393 }
00394
00395
00396 XMLNode* XMLNode::getChildNode(const JString& childPath)
00397 {
00398 if (childTags == NULL)
00399 return NULL;
00400
00401
00402
00403
00404
00405
00406
00407
00408 XMLNode* node;
00409 for (int i = 0; i < childTags->getCount(); i++) {
00410 if ( (node = (XMLNode*) childTags->get(i)) != NULL ) {
00411 if (node->getTag().equalsIgnoreCase(childPath)) {
00412 return(node);
00413 }
00414 }
00415 }
00416
00417 return(XMLNODENULL);
00418 }
00419
00420 ObjectCollection XMLNode::getChildNodes(Collection& childPath)
00421 {
00422 JString last = childPath.getLast();
00423 childPath.removeLast();
00424 XMLNode* node = getChildNode(childPath);
00425 childPath.addLast(last);
00426 if (node != NULL)
00427 return(node->getChildNodes(last));
00428 else {
00429 ObjectCollection oc;
00430 return(oc);
00431 }
00432 }
00433
00434 ObjectCollection XMLNode::getChildNodes(const JString& childPath)
00435 {
00436 XMLNode* node;
00437 ObjectCollection childNodes;
00438 if (childTags == NULL)
00439 return childNodes;
00440
00441 childNodes.noDelete();
00442
00443
00444
00445
00446
00447
00448 for (int i = 0; i < childTags->getCount(); i++) {
00449 if ( (node = (XMLNode*) childTags->get(i)) != NULL ) {
00450 if (node->getTag().equalsIgnoreCase(childPath)) {
00451 childNodes.add(node);
00452 }
00453 }
00454 }
00455
00456 return (childNodes);
00457
00458 }
00459
00460 ObjectCollection XMLNode::getAllNodes(const JString& childPath)
00461 {
00462 XMLNode* node;
00463 ObjectCollection allNodes;
00464 ObjectCollection tempNodes;
00465 allNodes.noDelete();
00466 if (childTags == NULL)
00467 return allNodes;
00468
00469 for (int i = 0; i < childTags->getCount(); i++) {
00470 if ( (node = (XMLNode*) childTags->get(i)) != NULL ) {
00471 if ((node->getTag()).equalsIgnoreCase(childPath)) {
00472 allNodes.add(node);
00473 }
00474
00475
00476 }
00477 }
00478
00479 return allNodes;
00480 }
00481
00482 XMLNode* XMLNode::getNodeWithAttrValue(Collection& attrPath, const JString& attrValue)
00483 {
00484 XMLNode* node;
00485 JString attr = attrPath.getLast();
00486 attrPath.removeLast();
00487
00488 ObjectCollection nodes = getChildNodes(attrPath);
00489
00490
00491
00492
00493
00494 for (int i = 0; i < nodes.getCount(); i++) {
00495 if ( (node = (XMLNode*) nodes.get(i)) != NULL ) {
00496 if (node->findAttr(attr).equalsIgnoreCase(attrValue)) {
00497 return(node);
00498 }
00499 }
00500 }
00501 return(XMLNODENULL);
00502 }
00503
00504 void XMLNode::setParent(XMLNode *p)
00505 {
00506 parent = p;
00507 }
00508
00509 XMLNode * XMLNode::getParent() const
00510 {
00511 return parent;
00512 }
00513
00514 Collection XMLNode::getPath() const
00515 {
00516 Collection path;
00517 path.addFirst(this->tag);
00518 for ( XMLNode* n = this->getParent();
00519 n != NULL;
00520 n = n->getParent()) {
00521 path.addFirst(n->tag);
00522 }
00523 return (path);
00524 }
00525
00526 JString XMLNode::asXMLOpenTag()
00527 {
00528
00529 JString xml;
00530
00531
00532 xml += "<";
00533 xml += tag;
00534
00535
00536 if (attributes != NULL) {
00537 for ( JString a = attributes->getFirstKey();
00538 ! ISJSTRINGNULL(a);
00539 a = attributes->getNextKey()) {
00540 xml += " ";
00541 xml += a;
00542 xml += "=\"";
00543 xml += attributes->get(a);
00544 xml += "\"";
00545 }
00546 }
00547
00548
00549 if ((text.length() == 0) &&
00550 ( (childTags == NULL) ||
00551 (childTags->getCount() == 0)) ) {
00552 xml += " />\n";
00553 } else {
00554 xml += ">";
00555 }
00556 return(xml);
00557 }
00558
00559
00560 JString XMLNode::asXMLCloseTag()
00561 {
00562
00563 JString xml;
00564
00565
00566 xml += "</";
00567 xml += tag;
00568 xml += ">";
00569 return(xml);
00570 }
00571
00572 bool XMLNode::setComment(const JString& t) {
00573 return setPreComment(t);
00574 }
00575
00576 bool XMLNode::setPreComment(const JString& t) {
00577 if (preComment.length() == 0)
00578 preComment = t;
00579 else
00580 preComment = JString::format("%s\n%s", (char*) preComment, (char*) t);
00581 return true;
00582 }
00583
00584 bool XMLNode::setPostComment(const JString& t) {
00585 if (postComment.length() == 0)
00586 postComment = t;
00587 else
00588 postComment = JString::format("%s\n%s", (char*) postComment, (char*) t);
00589 return true;
00590 }
00591
00592 JString XMLNode::getComment() const {
00593 return getPreComment();
00594 }
00595
00596 JString XMLNode::getPreComment() const {
00597 return preComment;
00598 }
00599
00600 JString XMLNode::getPostComment() const {
00601 return postComment;
00602 }
00603
00604 bool XMLNode::isCommentNode() const {
00605 return ( (preComment.length() > 0) || (postComment.length() > 0) );
00606 }
00607
00608 bool XMLNode::setDirective(const JString& t) {
00609 directive = t;
00610 return true;
00611 }
00612
00613 JString XMLNode::getDirective() const {
00614 return directive;
00615 }
00616
00617 bool XMLNode::isDirectiveNode() const {
00618 return (directive.length() > 0);
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 }