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 "XMLParser.h"
00026
00027 namespace cmlabs {
00028
00029
00030
00031
00032
00033
00034 XMLParser::XMLParser()
00035 {
00036 isXMLUTF = false;
00037 parseComments = false;
00038 nodeStack.noDelete();
00039 xmlUrl = JString("");
00040 xmlNode = NULL;
00041 reset();
00042 }
00043
00044 XMLParser::XMLParser(char url[])
00045 {
00046 isXMLUTF = false;
00047 parseComments = false;
00048 nodeStack.noDelete();
00049 xmlUrl = JString(url);
00050 xmlNode = NULL;
00051 reset();
00052 }
00053
00054 XMLParser::~XMLParser()
00055 {
00056
00057 deleteAllNodes();
00058 }
00059
00060 void XMLParser::deleteAllNodes() {
00061
00062 if (xmlNode == NULL) return;
00063 xmlNode->deleteAllChildNodes();
00064
00065 delete(xmlNode);
00066 }
00067
00068 void XMLParser::reset()
00069 {
00070 isXMLUTF = false;
00071 errorString = "";
00072 currLine = "";
00073 buf = "";
00074 deleteAllNodes();
00075 tagDepth = 0;
00076 line = 0;
00077 tagOpen =
00078 tagClose =
00079 attrTag =
00080 singleQuoteOpen =
00081 doubleQuoteOpen =
00082 commentOpen = false;
00083
00084
00085
00086
00087 xmlNode = currNode = new XMLNode();
00088 xmlNode->setParent(NULL);
00089 xml = "";
00090 }
00091
00092 bool XMLParser::isUTF() {
00093 return isXMLUTF;
00094 }
00095
00096 bool XMLParser::getXmlUrl() const
00097 {
00098
00099 return false;
00100
00101
00102 }
00103
00104 void XMLParser::setXmlUrl(const JString& url)
00105 {
00106 xmlUrl = url;
00107 }
00108
00109 XMLNode* XMLParser::getRootNode() const {
00110 if (xmlNode == NULL)
00111 return NULL;
00112 if (xmlNode->isEmpty())
00113 return NULL;
00114 return(xmlNode);
00115 }
00116
00117 void XMLParser::setRootNode(XMLNode* node) {
00118 xmlNode = node;
00119 }
00120
00121
00122 bool XMLParser::parse()
00123 {
00124 JString xml = JFile::readAFileASCII(xmlUrl);
00125 if (xml.length() == 0)
00126 return false;
00127 return parseXML(xml);
00128 }
00129
00130 bool XMLParser::parseXML(const JString& s) {
00131 return parse(s);
00132 }
00133
00134 bool XMLParser::parseURL(const JString& url)
00135 {
00136 setXmlUrl(url);
00137 return parse();
00138 }
00139
00140 bool XMLParser::isCloseComment(const JString& s) const {
00141 return (s.equals(JString("-->")));
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 bool XMLParser::parse(const JString& s)
00151 {
00152 reset();
00153 xml = s;
00154
00155 if (xml.isUTF())
00156 isXMLUTF = true;
00157 parseLine(s);
00158 return true;
00159 }
00160
00161
00162
00163 bool XMLParser::parseLine(const JString& s)
00164 {
00165 XMLNode* node, *temp;
00166 int startChar = 0;
00167 if (isXMLUTF)
00168 startChar = 3;
00169
00170 int curlineno = 1;
00171 int curcharno = 0;
00172 char* ch = (char*) s;
00173 currLine = s;
00174 int l = s.length();
00175
00176 for (int i = startChar;i < l; i++) {
00177 curcharno++;
00178
00179 if (commentOpen) {
00180 if (i < (l-2)) {
00181 if ( (ch[i] == '-') && (ch[i+1] == '-') && (ch[i+2] == '>') ) {
00182 commentOpen = false;
00183 i += 2;
00184 curcharno+=2;
00185 buf = buf.trim().trimLines();
00186 if (buf.length() > 0) {
00187 if (!addXMLCommentNode(buf, curlineno, curcharno)) {
00188 errorString += JString::format("Could not add comment node at line %d column %d\n", curlineno, curcharno);
00189 return false;
00190 }
00191
00192 }
00193 buf = "";
00194
00195 }
00196 else if ( (ch[i] == '?') && (ch[i+1] == '>') ) {
00197 commentOpen = false;
00198 i += 1;
00199 curcharno++;
00200 buf = buf.trim().trimLines();
00201 if (buf.length() > 0) {
00202 if (!addXMLDirectiveNode(buf, curlineno, curcharno)) {
00203 errorString += JString::format("Could not add directive node at line %d column %d\n", curlineno, curcharno);
00204 return false;
00205 }
00206
00207 }
00208 buf = "";
00209
00210 }
00211 else
00212 buf += ch[i];
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222 }
00223 else {
00224
00225 switch(ch[i]) {
00226 case ' ':
00227 if (doubleQuoteOpen) {
00228 buf += ch[i];
00229 break;
00230 }
00231 case '\t':
00232 if (tagOpen &&
00233 (buf.length() > 0)) {
00234 if (!addXMLNode(buf, curlineno, curcharno)) {
00235 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00236 return false;
00237 }
00238 buf = "";
00239 } else {
00240 if ((!tagOpen) && (!tagClose)) {
00241 buf += ch[i];
00242 }
00243 }
00244 break;
00245
00246
00247 case '<':
00248
00249 if (ch[i+1] == '\?') {
00250
00251 commentOpen = true;
00252 i += 1;
00253
00254 } else if (ch[i+1] == '!') {
00255 commentOpen = true;
00256 if (ch[i+2] == '-') {
00257 if (ch[i+3] == '-')
00258 i += 2;
00259 else
00260 i += 1;
00261 }
00262 i += 1;
00263 break;
00264 }
00265
00266
00267 if (ch[i+1] != '/') {
00268 tagOpen = true;
00269
00270 if (buf.trim().length() > 0) {
00271 if (!addXMLNode("", curlineno, curcharno)) {
00272 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00273 return false;
00274 }
00275 currNode->setText(JString(buf).trim().trimLines().xmlStringDecode());
00276 currNode = popNode();
00277 }
00278 buf = "";
00279 }
00280 else {
00281 tagClose = true;
00282 if (currNode == NULL) {
00283 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00284 return false;
00285 }
00286 else {
00287 if (buf.trim().length() > 0) {
00288 if ( (currNode->childTags != NULL) && (currNode->childTags->getCount() > 0)) {
00289 if (!addXMLNode("", curlineno, curcharno)) {
00290 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00291 return false;
00292 }
00293 currNode->setText(JString(buf).trim().trimLines().xmlStringDecode());
00294 currNode = popNode();
00295 }
00296 else
00297 currNode->setText(JString(buf).trim().trimLines().xmlStringDecode());
00298 }
00299 }
00300 buf = "";
00301 }
00302
00303
00304 if (tagOpen) {
00305 tagDepth++;
00306 }
00307 break;
00308
00309
00310 case '>':
00311 if (tagOpen) {
00312 tagOpen = false;
00313 if (!attrTag) {
00314 if (!addXMLNode(buf, curlineno, curcharno)) {
00315 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00316 return false;
00317 }
00318 #if 0 // Should be unnecessary - AKR - 7/12/2001 - Handled above in space/tab case
00319 } else if (currNode->isEmpty()) {
00320 if (!addXMLNode(buf, curlineno, curcharno)) {
00321 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00322 return false;
00323 }
00324 #endif
00325 }
00326 attrTag = false;
00327 } else if (tagClose) {
00328
00329 if (currNode == NULL) {
00330 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00331 return false;
00332 }
00333
00334 if ( (currNode->getTag().length() == 0) && (currNode->isCommentNode()) && (currNode->parent != NULL) ) {
00335
00336 currNode->parent->childTags->removeNoDelete(currNode);
00337 if ( (node = (XMLNode*) currNode->parent->childTags->getLast()) != NULL) {
00338 node->setPostComment(currNode->getPreComment());
00339 }
00340 else {
00341 currNode->parent->setPreComment(currNode->getPreComment());
00342 }
00343 temp = currNode;
00344 currNode = popNode();
00345 delete(temp);
00346 }
00347
00348 if ( (buf.length() > 0) && (currNode->getTag().equalsIgnoreCase(buf))) {
00349 tagClose = false;
00350 tagDepth--;
00351
00352
00353
00354 currNode = popNode();
00355 }
00356 else {
00357 errorString += JString::format("Node '%s' in line %d column %d did not have an end node,\n| was ended by '%s' at line %d column %d\n",
00358 (char*) currNode->getTag(), currNode->lineno, currNode->charno, (char*) buf, curlineno, curcharno-buf.length()-1);
00359 }
00360 }
00361 buf = "";
00362 break;
00363
00364
00365 case '/':
00366 if ((!tagOpen) && (!tagClose)) {
00367
00368 buf += ch[i];
00369 break;
00370 }
00371
00372 if (ch[i+1] == '>') {
00373 tagOpen = false;
00374
00375 if (doubleQuoteOpen) {
00376 if (currNode != NULL) {
00377 errorString += JString::format("Attribute syntax error for tag '%s' at line %d column %d\n",
00378 (char*) currNode->getTag(), curlineno, curcharno);
00379 }
00380 else {
00381 errorString += JString::format("Attribute syntax error for at line %d column %d\n",
00382 curlineno, curcharno);
00383 }
00384 return false;
00385 }
00386 if (buf.length() > 0) {
00387 if (!addXMLNode(buf, curlineno, curcharno)) {
00388 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00389 return false;
00390 }
00391 }
00392 attrTag = false;
00393 buf = "";
00394
00395 tagDepth--;
00396 currNode = popNode();
00397 i += 1;
00398 curcharno++;
00399
00400 } else if (tagClose) {
00401
00402
00403
00404 } else {
00405
00406 buf += ch[i];
00407 }
00408 break;
00409
00410 case '=':
00411 if ((!tagOpen) && (!tagClose)) {
00412
00413 buf += ch[i];
00414 break;
00415 }
00416 if (doubleQuoteOpen) {
00417 buf += ch[i];
00418 break;
00419 }
00420 attrTag = true;
00421 break;
00422
00423 case '\"':
00424 if ((!tagOpen) && (!tagClose)) {
00425
00426 buf += ch[i];
00427 break;
00428 }
00429 if (doubleQuoteOpen) {
00430 doubleQuoteOpen = false;
00431 if (!addXMLAttrAndValue(attr,buf)) {
00432 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00433 return false;
00434 }
00435 attr = buf = "";
00436 } else {
00437 doubleQuoteOpen = true;
00438 attr = buf;
00439 buf = "";
00440 }
00441 break;
00442
00443 case '\'':
00444 if ((!tagOpen) && (!tagClose)) {
00445
00446 buf += ch[i];
00447 break;
00448 }
00449 if (singleQuoteOpen) {
00450 singleQuoteOpen = false;
00451 if (!addXMLAttrAndValue(attr,buf)) {
00452 errorString += JString::format("Parsing beyond end of XML at line %d column %d\n", curlineno, curcharno);
00453 return false;
00454 }
00455 attr = buf = "";
00456 } else {
00457 singleQuoteOpen = true;
00458 attr = buf;
00459 buf = "";
00460 }
00461 break;
00462
00463 case '\r':
00464 buf += '\n';
00465 break;
00466 case '\n':
00467 curlineno++;
00468 curcharno=0;
00469 buf += '\n';
00470 break;
00471
00472 default:
00473 buf += ch[i];
00474 break;
00475
00476 }
00477 }
00478 }
00479
00480 if (nodeStack.getCount() > 0) {
00481 XMLNode* errnode;
00482 for (int n=0; n<nodeStack.getCount(); n++) {
00483 errnode = (XMLNode *) nodeStack.get(n);
00484 errorString += JString::format("Node '%s' in line %d column %d did not have an end node\n", (char*) errnode->getTag(), errnode->lineno, errnode->charno);
00485 }
00486 }
00487 if (currNode != NULL) {
00488 errorString += JString::format("Node '%s' in line %d column %d did not have an end node\n", (char*) currNode->getTag(), currNode->lineno, currNode->charno);
00489 }
00490 return (errorString.length() == 0);
00491 }
00492
00493
00494 void XMLParser::pushNode(XMLNode *node)
00495 {
00496 nodeStack.addLast((Object *) node);
00497
00498 }
00499
00500 XMLNode* XMLParser::popNode()
00501 {
00502
00503 XMLNode* node = (XMLNode *) nodeStack.getLast();
00504 nodeStack.removeLast();
00505 if (DEBUGLEVEL(KITCHENSINK)) {
00506 printNodeStack("popNode");
00507 }
00508 if (node != NULL) {
00509
00510
00511 }
00512 currNode = node;
00513 return(node);
00514 }
00515
00516
00517 JString XMLParser::trimLeadingWhite(char *s) const {
00518 JString s2;
00519 int i, l = (int) strlen(s);
00520 bool leadingWhite = true;
00521 for (i = 0; i < l;i++) {
00522 if (leadingWhite) {
00523 if (! (s[i] == ' ' || s[i] == '\t')) {
00524 leadingWhite = false;
00525 }
00526 }
00527 if (! leadingWhite) {break;}
00528 }
00529 if (i == l) {
00530 s2 = "";
00531 } else {
00532 s2 = JString(&s[i]);
00533 }
00534 return(s2);
00535 }
00536
00537 bool XMLParser::addXMLNode(const JString& s, int line, int col)
00538 {
00539 if (currNode == NULL)
00540 return false;
00541
00542
00543
00544
00545 if (currNode->isEmpty()) {
00546 currNode->setTag(s.trim().xmlStringDecode());
00547 currNode->isXMLUTF = isXMLUTF;
00548 } else {
00549 XMLNode *temp = new XMLNode(s.trim().xmlStringDecode());
00550 temp->isXMLUTF = isXMLUTF;
00551 temp->setParent(currNode);
00552 pushNode(currNode);
00553 currNode->addChildTag((Object *) temp);
00554 currNode = temp;
00555 if (DEBUGLEVEL(KITCHENSINK)) {
00556 printNodeStack("pushNode");
00557 }
00558 }
00559 currNode->lineno = line;
00560 currNode->charno = col;
00561
00562 return true;
00563 }
00564
00565
00566 bool XMLParser::addXMLCommentNode(const JString& s, int line, int col)
00567 {
00568 if (currNode == NULL) {
00569 if (this->nodeStack.getCount() == 0) {
00570 if (this->xmlNode != NULL) {
00571 xmlNode->setPostComment(s.xmlStringDecode());
00572
00573 return true;
00574 }
00575 }
00576 return false;
00577 }
00578
00579 currNode->isXMLUTF = isXMLUTF;
00580
00581 if (currNode->isEmpty()) {
00582 currNode->setPreComment(s.xmlStringDecode());
00583 } else {
00584 XMLNode *temp = new XMLNode("");
00585
00586 temp->isXMLUTF = isXMLUTF;
00587 temp->setComment(s.xmlStringDecode());
00588 temp->setParent(currNode);
00589 pushNode(currNode);
00590 currNode->addChildTag((Object *) temp);
00591 currNode = temp;
00592 if (DEBUGLEVEL(KITCHENSINK)) {
00593 printNodeStack("pushNode");
00594 }
00595 }
00596 currNode->lineno = line;
00597 currNode->charno = col;
00598
00599 return true;
00600 }
00601
00602 bool XMLParser::addXMLDirectiveNode(const JString& s, int line, int col)
00603 {
00604 if (currNode == NULL)
00605 return false;
00606
00607 currNode->isXMLUTF = isXMLUTF;
00608
00609 if (currNode->isEmpty()) {
00610 currNode->setDirective(s.xmlStringDecode());
00611 } else {
00612 XMLNode *temp = new XMLNode("");
00613 temp->isXMLUTF = isXMLUTF;
00614 temp->setDirective(s.xmlStringDecode());
00615 temp->setParent(currNode);
00616 pushNode(currNode);
00617 currNode->addChildTag((Object *) temp);
00618 currNode = temp;
00619 if (DEBUGLEVEL(KITCHENSINK)) {
00620 printNodeStack("pushNode");
00621 }
00622 }
00623 currNode->lineno = line;
00624 currNode->charno = col;
00625
00626 return true;
00627 }
00628
00629 bool XMLParser::addXMLAttrAndValue(const JString& attr, const JString& value)
00630 {
00631 if (currNode == NULL) {
00632 return false;
00633 }
00634
00635 currNode->addAttribute(attr.xmlStringDecode(),value.xmlStringDecode());
00636 return true;
00637 }
00638
00639
00640 void XMLParser::printNodeStack(char *s)
00641 {
00642 return;
00643 JString xml = JString(s);
00644 xml += JString(" NodeStack\n");
00645 xml += "currLine[";
00646 xml += JString(line);
00647 xml += "]:";
00648 xml += currLine;
00649 xml += "\n";
00650 xml += "currNode: ";
00651 if (currNode) {
00652 xml += currNode->getTag();
00653 } else {
00654 xml += "NULL";
00655 }
00656 xml += "\n";
00657
00658
00659
00660
00661
00662 XMLNode* node;
00663 for (int i=0; i<nodeStack.getCount(); i++) {
00664 if ( (node = (XMLNode*) nodeStack.get(i)) != NULL )
00665 xml += node->getTag();
00666 xml += "\n";
00667 }
00668 printf("%s\n",xml.charpoint());
00669 }
00670
00671 JString XMLParser::asXML()
00672 {
00673 return (xmlNode->asXML());
00674
00675 }
00676
00677 JString XMLParser::asXMLWithCRs()
00678 {
00679 return (xmlNode->asXMLWithCRs());
00680
00681 }
00682
00683 ObjectCollection XMLParser::getAllNodes(const JString& childPath) const {
00684 return (xmlNode->getAllNodes(childPath));
00685 }
00686
00687 XMLNode* XMLParser::getNodeWithAttrValue(Collection& attrPath, const JString& attrValue) const {
00688
00689 return (xmlNode->getNodeWithAttrValue(attrPath,attrValue));
00690 }
00691
00692 ObjectCollection* XMLParser::getChildTags() {
00693 return (xmlNode->getChildTags());
00694 }
00695
00696
00697
00698
00699
00700
00701 JString XMLParser::findAttr(const JString& attr) const
00702 {
00703 return (xmlNode->findAttr(attr));
00704 }
00705
00706 XMLNode* XMLParser::getChildNode(Collection& childPath) const
00707 {
00708 if ( (childPath.getCount() == 1) && (xmlNode->getTag().equalsIgnoreCase(childPath.getFirst())) )
00709 return xmlNode;
00710 return (xmlNode->getChildNode(childPath));
00711 }
00712
00713 XMLNode* XMLParser::getChildNode(const JString& childPath) const
00714 {
00715 if (xmlNode->getTag().equalsIgnoreCase(childPath))
00716 return xmlNode;
00717 return (xmlNode->getChildNode(childPath));
00718 }
00719
00720 ObjectCollection XMLParser::getChildNodes(const JString& childPath) const {
00721 return (xmlNode->getChildNodes(childPath));
00722 }
00723
00724 ObjectCollection XMLParser::getChildNodes(Collection& childPath) const {
00725 return (xmlNode->getChildNodes(childPath));
00726 }
00727
00728 Dictionary* XMLParser::getAttributes() {
00729 return (xmlNode->getAttributes());
00730 }
00731
00732
00733 JString XMLParser::getErrorString() {
00734 return errorString;
00735 }
00736
00737 JString XMLParser::verifyXML(const JString& xml) {
00738 reset();
00739 parseXML(xml);
00740 return errorString;
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 bool XMLParser::unitTest()
00752 {
00753
00754
00755
00756 JString str, exp, xml, error;
00757 XMLNode* xmlNode;
00758 XMLParser* xmlParser;
00759 XMLNode* entry;
00760 Dictionary* parm;
00761 JString s, ss;
00762 ObjectCollection states;
00763
00764
00765 xmlParser = new XMLParser();
00766
00767 str = "<tag/>";
00768 exp = "<tag />";
00769 error = xmlParser->verifyXML(str);
00770 if (error.length() > 0) {
00771 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00772 return false;
00773 }
00774 xmlNode = xmlParser->getRootNode();
00775 if (xmlNode == NULL) {
00776 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00777 return false;
00778 }
00779 xml = xmlNode->toXML().trimCTRL();
00780 if (!xml.equalsIgnoreCase(exp)) {
00781 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00782 return false;
00783 }
00784
00785 str = "<tag />";
00786 exp = "<tag />";
00787 error = xmlParser->verifyXML(str);
00788 if (error.length() > 0) {
00789 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00790 return false;
00791 }
00792 xmlNode = xmlParser->getRootNode();
00793 if (xmlNode == NULL) {
00794 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00795 return false;
00796 }
00797 xml = xmlNode->toXML().trimCTRL();
00798 if (!xml.equalsIgnoreCase(exp)) {
00799 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00800 return false;
00801 }
00802
00803 str = "<tag param='test' />";
00804 exp = "<tag param=\"test\" />";
00805 error = xmlParser->verifyXML(str);
00806 if (error.length() > 0) {
00807 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00808 return false;
00809 }
00810 xmlNode = xmlParser->getRootNode();
00811 if (xmlNode == NULL) {
00812 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00813 return false;
00814 }
00815 xml = xmlNode->toXML().trimCTRL();
00816 if (!xml.equalsIgnoreCase(exp)) {
00817 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00818 return false;
00819 }
00820
00821 str = "<tag>bla 'bla' bla</tag>";
00822 exp = "<tag>bla 'bla' bla</tag>";
00823 error = xmlParser->verifyXML(str);
00824 if (error.length() > 0) {
00825 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00826 return false;
00827 }
00828 xmlNode = xmlParser->getRootNode();
00829 if (xmlNode == NULL) {
00830 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00831 return false;
00832 }
00833 xml = xmlNode->toXML().trimCTRL();
00834 if (!xml.equalsIgnoreCase(exp)) {
00835 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00836 return false;
00837 }
00838
00839 str = "<tag>bla <tag2>blu</tag2> bla</tag>";
00840 exp = "<tag>bla<tag2>blu</tag2>bla</tag>";
00841 error = xmlParser->verifyXML(str);
00842 if (error.length() > 0) {
00843 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00844 return false;
00845 }
00846 xmlNode = xmlParser->getRootNode();
00847 if (xmlNode == NULL) {
00848 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00849 return false;
00850 }
00851 xml = xmlNode->toXML().trimCTRL();
00852 if (!xml.equalsIgnoreCase(exp)) {
00853 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00854 return false;
00855 }
00856
00857 str = "<tag value=\"bla > bla < bla\">blabla</tag>";
00858 exp = "<tag value=\"bla > bla < bla\">blabla</tag>";
00859 error = xmlParser->verifyXML(str);
00860 if (error.length() > 0) {
00861 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00862 return false;
00863 }
00864 xmlNode = xmlParser->getRootNode();
00865 if (xmlNode == NULL) {
00866 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00867 return false;
00868 }
00869 xml = xmlNode->toXML().trimCTRL();
00870 if (!xml.equalsIgnoreCase(exp)) {
00871 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00872 return false;
00873 }
00874
00875
00876 str = "<tag>\n\tline1\n\tline2\n\tline3\n</tag>\n";
00877 exp = "<tag>\n\tline1\n\tline2\n\tline3\n</tag>\n";
00878 error = xmlParser->verifyXML(str);
00879 if (error.length() > 0) {
00880 addUnitTestLog(JString::format("Couldn't parse %s correctly:\n%s\n", (char*) str, (char*) error));
00881 return false;
00882 }
00883 xmlNode = xmlParser->getRootNode();
00884 if (xmlNode == NULL) {
00885 addUnitTestLog(JString::format("Couldn't parse %s correctly: No errors, just no content", (char*) str));
00886 return false;
00887 }
00888
00889 xml = xmlNode->toXML();
00890
00891
00892 if (!xml.equalsIgnoreCase(exp)) {
00893 addUnitTestLog(JString::format("Couldn't parse %s correctly, got %s", (char*) str, (char*) xml));
00894 return false;
00895 }
00896
00897
00898
00899 delete (xmlParser);
00900
00901 str = "<dictionary>";
00902 str += "<entry key=\"key0\" value=\"value0\" />";
00903 str += "<entry key=\"key1\" value=\"value1\" />";
00904 str += "<entry key=\"key2\" value=\"value2\" />";
00905 str += "<entry key=\"key3\" value=\"value3\" />";
00906 str += "<entry key=\"key4\" value=\"value4\" />";
00907 str += "<entry key=\"key5\" value=\"value5\" />";
00908 str += "<entry key=\"key6\" value=\"value6\" />";
00909 str += "<entry key=\"key7\" value=\"value7\" />";
00910 str += "<entry key=\"key8\" value=\"value8\" />";
00911 str += "<entry key=\"key9\" value=\"value9\" />";
00912 str += "</dictionary>";
00913
00914 xmlParser = new XMLParser();
00915 error = xmlParser->verifyXML(str);
00916 if (error.length() > 0) {
00917 addUnitTestLog(JString::format("Could not parse dictionary node in XML:\n%s\n", (char*) error));
00918 return false;
00919 }
00920
00921 xmlNode = xmlParser->getChildNode("dictionary");
00922 if (xmlNode == NULL) {
00923 addUnitTestLog("Could not find dictionary node in XML...");
00924 return false;
00925 }
00926
00927 ss = xmlNode->asXML();
00928
00929
00930
00931
00932 error = xmlParser->verifyXML(ss);
00933 if (error.length() > 0) {
00934 addUnitTestLog(JString::format("Could not parse dictionary node 2 in XML:\n%s\n", (char*) error));
00935 return false;
00936 }
00937
00938 xmlNode = xmlParser->getChildNode("dictionary");
00939 if (xmlNode == NULL) {
00940 addUnitTestLog("Could not find dictionary node 2 in XML...");
00941 return false;
00942 }
00943
00944
00945 xml = xmlNode->asXML();
00946 if (!xml.trimCTRL().equalsIgnoreCase(str)) {
00947 addUnitTestLog(JString::format("Couldn't parse dictionary 2 correctly, got %s", (char*) xml));
00948 return false;
00949 }
00950
00951
00952
00953 xmlNode = xmlParser->getChildNode("dictionary");
00954
00955 ObjectCollection* col = xmlNode->getChildTags();
00956
00957 if ( (col == NULL) || (col->getCount() != 10) ) {
00958 addUnitTestLog(JString::format("Dictionary didn't have 10 childen as expected..."));
00959 return false;
00960 }
00961
00962 for (int n=0; n<col->getCount(); n++) {
00963 entry = (XMLNode*) col->get(n);
00964 if (entry->getTag().equalsIgnoreCase("entry")) {
00965 parm = entry->getAttributes();
00966 if ((parm == NULL) || (parm->getCount() != 2)) {
00967 addUnitTestLog(JString::format("Dictionary entry did not have 2 params"));
00968 return false;
00969 }
00970 s = JString("key") + JString(n);
00971 if (parm->get("key") != s) {
00972 addUnitTestLog(JString::format("Dictionary entry did not have the right key (%s != %s)", (char*) parm->get("key"), (char*) s));
00973 return false;
00974 }
00975 s = JString("value") + JString(n);
00976 if (parm->get("value") != s) {
00977 addUnitTestLog(JString::format("Dictionary entry did not have the right value (%s != %s)", (char*) parm->get("value"), (char*) s));
00978 return false;
00979 }
00980 }
00981 else {
00982 addUnitTestLog(JString::format("Dictionary entry did not correct tag 'entry' (%s)", (char*) entry->getTag()));
00983 return false;
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994 delete(xmlParser);
00995
00996 str = "<Qvalues name=\"test\"><State name=\"UUU\"><Action name=\"other_giving\" visited=\"0\" value=\"-0.9948462247926799\" /><Action name=\"other_holding\" visited=\"0\" value=\" 0.0\" /></State></Qvalues>";
00997
00998 xmlParser = new XMLParser();
00999 error = xmlParser->verifyXML(str);
01000 if (error.length() > 0) {
01001 addUnitTestLog(JString::format("Could not parse Qvalues XML:\n%s\n", (char*) error));
01002 return false;
01003 }
01004
01005 xmlNode = xmlParser->getRootNode();
01006 if (xmlNode == NULL) {
01007 addUnitTestLog("Could not understant Qvalues XML...");
01008 return false;
01009 }
01010
01011 ss = xmlNode->asXML().removeCRs();
01012 ss.replace("\t", "", true, true);
01013
01014 if (!str.equals(ss)) {
01015 addUnitTestLog(JString::format("\nUpper/LowerCase test Failed: \n%s\n%s\n\n", (char*) str, (char*) ss));
01016 return false;
01017 }
01018
01019 if ( (entry = xmlNode->getChildNode("State")) == NULL) {
01020 addUnitTestLog("No childnode State for Qvalues XML...");
01021 return false;
01022 }
01023 if (entry->getAttribute("name").length() == 0) {
01024 addUnitTestLog("No attribude name for Qvalues XML...");
01025 return false;
01026 }
01027
01028 if ( (entry = xmlNode->getChildNode("state")) == NULL) {
01029 addUnitTestLog("No childnode lowercase State for Qvalues XML...");
01030 return false;
01031 }
01032 if (entry->getAttribute("name").length() == 0) {
01033 addUnitTestLog("No attribude name for Qvalues XML...");
01034 return false;
01035 }
01036
01037 states = xmlNode->getChildNodes("State");
01038 if (states.getCount() != 1) {
01039 addUnitTestLog("Not 1 State childnode for Qvalues XML...");
01040 return false;
01041 }
01042
01043 states = entry->getChildNodes("Action");
01044 if (states.getCount() != 2) {
01045 addUnitTestLog("Not 2 Action childnode for Qvalues XML...");
01046 return false;
01047 }
01048
01049 states = entry->getChildNodes("action");
01050 if (states.getCount() != 2) {
01051 addUnitTestLog("Not 2 lowercase Action childnode for Qvalues XML...");
01052 return false;
01053 }
01054
01055 delete(xmlParser);
01056
01057
01058
01059
01060 str = "<!-- Comment One --><Qvalues name=\"test\"><!-- Comment Two --><State name=\"UUU\"><!-- Comment Three --><Action name=\"other_giving\" visited=\"0\" value=\"-0.9948462247926799\" /><!-- Comment Four --><Action name=\"other_holding\" visited=\"0\" value=\" 0.0\" /><!-- Comment Five --></State><!-- Comment Six --></Qvalues><!-- Comment Seven -->";
01061
01062
01063 xmlParser = new XMLParser();
01064 error = xmlParser->verifyXML(str);
01065 if (error.length() > 0) {
01066 addUnitTestLog(JString::format("Could not parse Commented Qvalues XML:\n%s\n", (char*) error));
01067 return false;
01068 }
01069
01070 xmlNode = xmlParser->getRootNode();
01071 if (xmlNode == NULL) {
01072 addUnitTestLog("Could not understant Commented Qvalues XML...");
01073 return false;
01074 }
01075
01076 if (!xmlNode->getComment().equalsIgnoreCase("Comment One")) {
01077 addUnitTestLog(JString::format("\nOuter Comment One failed\n\n"));
01078 return false;
01079 }
01080 if (!xmlNode->getPostComment().equalsIgnoreCase("Comment Seven")) {
01081 addUnitTestLog(JString::format("\nComment Seven failed\n\n"));
01082 return false;
01083 }
01084
01085 if ( (entry = xmlNode->getChildNode("State")) == NULL) {
01086 addUnitTestLog("No childnode State for Commented Qvalues XML...");
01087 return false;
01088 }
01089 if (!entry->getComment().equalsIgnoreCase("Comment Two")) {
01090 addUnitTestLog(JString::format("\nComment Two failed\n\n"));
01091 return false;
01092 }
01093 if (!entry->getPostComment().equalsIgnoreCase("Comment Six")) {
01094 addUnitTestLog(JString::format("\nComment Six failed\n\n"));
01095 return false;
01096 }
01097
01098 states = entry->getChildNodes("Action");
01099 if (states.getCount() != 2) {
01100 addUnitTestLog("Not 2 Action childnode for Commented Qvalues XML...");
01101 return false;
01102 }
01103
01104 if ( (entry = (XMLNode*) states.getFirst()) == NULL ) {
01105 addUnitTestLog("No first Action childnode for Commented Qvalues XML...");
01106 return false;
01107 }
01108 if (!entry->getComment().equalsIgnoreCase("Comment Three")) {
01109 addUnitTestLog(JString::format("\nComment Three failed\n\n"));
01110 return false;
01111 }
01112
01113 if ( (entry = (XMLNode*) states.getLast()) == NULL ) {
01114 addUnitTestLog("No last Action childnode for Commented Qvalues XML...");
01115 return false;
01116 }
01117 if (!entry->getComment().equalsIgnoreCase("Comment Four")) {
01118 addUnitTestLog(JString::format("\nComment Four failed\n\n"));
01119 return false;
01120 }
01121 if (!entry->getPostComment().equalsIgnoreCase("Comment Five")) {
01122 addUnitTestLog(JString::format("\nComment Five failed\n\n"));
01123 return false;
01124 }
01125
01126 delete(xmlParser);
01127
01128
01129 char* ch = new char[10000];
01130 strcpy(ch, "xxx<?xml version=\"1.0\" encoding=\"UTF-8\"?><JapaneseText>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</JapaneseText>");
01131 *((unsigned char*)(ch)) = 239;
01132 *((unsigned char*)(ch+1)) = 187;
01133 *((unsigned char*)(ch+2)) = 191;
01134 *((unsigned char*)(ch+55)) = 227;
01135 *((unsigned char*)(ch+56)) = 129;
01136 *((unsigned char*)(ch+57)) = 147;
01137 *((unsigned char*)(ch+58)) = 227;
01138 *((unsigned char*)(ch+59)) = 130;
01139 *((unsigned char*)(ch+60)) = 140;
01140 *((unsigned char*)(ch+61)) = 227;
01141 *((unsigned char*)(ch+62)) = 129;
01142 *((unsigned char*)(ch+63)) = 175;
01143 *((unsigned char*)(ch+64)) = 230;
01144 *((unsigned char*)(ch+65)) = 151;
01145 *((unsigned char*)(ch+66)) = 165;
01146 *((unsigned char*)(ch+67)) = 230;
01147 *((unsigned char*)(ch+68)) = 156;
01148 *((unsigned char*)(ch+69)) = 172;
01149 *((unsigned char*)(ch+70)) = 232;
01150 *((unsigned char*)(ch+71)) = 170;
01151 *((unsigned char*)(ch+72)) = 158;
01152 *((unsigned char*)(ch+73)) = 227;
01153 *((unsigned char*)(ch+74)) = 129;
01154 *((unsigned char*)(ch+75)) = 174;
01155 *((unsigned char*)(ch+76)) = 227;
01156 *((unsigned char*)(ch+77)) = 131;
01157 *((unsigned char*)(ch+78)) = 134;
01158 *((unsigned char*)(ch+79)) = 227;
01159 *((unsigned char*)(ch+80)) = 130;
01160 *((unsigned char*)(ch+81)) = 173;
01161 *((unsigned char*)(ch+82)) = 227;
01162 *((unsigned char*)(ch+83)) = 130;
01163 *((unsigned char*)(ch+84)) = 185;
01164 *((unsigned char*)(ch+85)) = 227;
01165 *((unsigned char*)(ch+86)) = 131;
01166 *((unsigned char*)(ch+87)) = 136;
01167 *((unsigned char*)(ch+88)) = 227;
01168 *((unsigned char*)(ch+89)) = 128;
01169 *((unsigned char*)(ch+90)) = 130;
01170
01171 str = ch;
01172
01173 xmlParser = new XMLParser();
01174 error = xmlParser->verifyXML(str);
01175 if (error.length() > 0) {
01176 addUnitTestLog(JString::format("Could not parse UTF-8 XML:\n%s\n", (char*) error));
01177 return false;
01178 }
01179
01180 xmlNode = xmlParser->getRootNode();
01181 if (xmlNode == NULL) {
01182 addUnitTestLog("Could not understand UTF-8 XML...");
01183 return false;
01184 }
01185
01186 if (!xmlNode->getTag().equalsIgnoreCase("JapaneseText")) {
01187 addUnitTestLog("Could not understand node tag UTF-8 XML...");
01188 return false;
01189 }
01190
01191 ss = xmlNode->getText();
01192 if (ss.length() == 0) {
01193 addUnitTestLog("Could not understand node content UTF-8 XML...");
01194 return false;
01195 }
01196
01197 #ifdef WIN32
01198
01199
01200 if (!ss.utf2unicode()) {
01201 addUnitTestLog("Could not convert node content UTF-8 XML...");
01202 return false;
01203 }
01204
01205
01206 JString sss = ss;
01207 if (!sss.unicode2utf()) {
01208 addUnitTestLog("Could not convert back node content UTF-8 XML...");
01209 return false;
01210 }
01211
01212 if (!sss.equals(ss)) {
01213 addUnitTestLog("Could not match node content UTF-8 XML...");
01214 return false;
01215 }
01216
01217 #endif // ifdef WIN32
01218
01219 ss = xmlNode->asXML().removeCRs();
01220 ss.replace("\t", "", true, true);
01221
01222 if (!str.equals(ss)) {
01223 addUnitTestLog(JString::format("\nUTF-8 test Failed: \n%s\n%s\n\n", (char*) str, (char*) ss));
01224 return false;
01225 }
01226
01227 delete(xmlParser);
01228 delete [] ch;
01229
01230 return true;
01231 }
01232
01233
01234 }