/home/dko/projects/mobilec/trunk/src/mxml-2.2.2/testmxml.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月24日) $ : Last Committed Date */
00004 /*
00005  * "$Id: testmxml.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $"
00006  *
00007  * Test program for Mini-XML, a small XML-like file parsing library.
00008  *
00009  * Copyright 2003-2005 by Michael Sweet.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Library General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019  * GNU General Public License for more details.
00020  *
00021  * Contents:
00022  *
00023  * main() - Main entry for test program.
00024  * type_cb() - XML data type callback for mxmlLoadFile()...
00025  * whitespace_cb() - Let the mxmlSaveFile() function know when to insert
00026  * newlines and tabs...
00027  */
00028 
00029 /*
00030  * Include necessary headers...
00031  */
00032 
00033 #include "config.h"
00034 #include "mxml.h"
00035 #ifdef WIN32
00036 # include <io.h>
00037 #else
00038 # include <unistd.h>
00039 #endif /* WIN32 */
00040 #include <fcntl.h>
00041 #ifndef O_BINARY
00042 # define O_BINARY 0
00043 #endif /* !O_BINARY */
00044 
00045 
00046 /*
00047  * Local functions...
00048  */
00049 
00050 mxml_type_t type_cb(mxml_node_t *node);
00051 const char *whitespace_cb(mxml_node_t *node, int where);
00052 
00053 
00054 /*
00055  * 'main()' - Main entry for test program.
00056  */
00057 
00058 int /* O - Exit status */
00059 main(int argc, /* I - Number of command-line args */
00060 char *argv[]) /* I - Command-line args */
00061 {
00062 int i; /* Looping var */
00063 FILE *fp; /* File to read */
00064 int fd; /* File descriptor */
00065 mxml_node_t *tree, /* XML tree */
00066 *node; /* Node which should be in test.xml */
00067 mxml_index_t *ind; /* XML index */
00068 char buffer[16384]; /* Save string */
00069 static const char *types[] = /* Strings for node types */
00070 {
00071 "MXML_ELEMENT",
00072 "MXML_INTEGER",
00073 "MXML_OPAQUE",
00074 "MXML_REAL",
00075 "MXML_TEXT"
00076 };
00077 
00078 
00079 /*
00080  * Check arguments...
00081  */
00082 
00083 if (argc != 2)
00084 {
00085 fputs("Usage: testmxml filename.xml\n", stderr);
00086 return (1);
00087 }
00088 
00089 /*
00090  * Test the basic functionality...
00091  */
00092 
00093 tree = mxmlNewElement(MXML_NO_PARENT, "element");
00094 
00095 if (!tree)
00096 {
00097 fputs("ERROR: No parent node in basic test!\n", stderr);
00098 return (1);
00099 }
00100 
00101 if (tree->type != MXML_ELEMENT)
00102 {
00103 fprintf(stderr, "ERROR: Parent has type %s (%d), expected MXML_ELEMENT!\n",
00104 tree->type < MXML_ELEMENT || tree->type > MXML_TEXT ?
00105 "UNKNOWN" : types[tree->type], tree->type);
00106 mxmlDelete(tree);
00107 return (1);
00108 }
00109 
00110 if (strcmp(tree->value.element.name, "element"))
00111 {
00112 fprintf(stderr, "ERROR: Parent value is \"%s\", expected \"element\"!\n",
00113 tree->value.element.name);
00114 mxmlDelete(tree);
00115 return (1);
00116 }
00117 
00118 mxmlNewInteger(tree, 123);
00119 mxmlNewOpaque(tree, "opaque");
00120 mxmlNewReal(tree, 123.4f);
00121 mxmlNewText(tree, 1, "text");
00122 
00123 mxmlLoadString(tree, "<group type='string'>string string string</group>",
00124 MXML_NO_CALLBACK);
00125 mxmlLoadString(tree, "<group type='integer'>1 2 3</group>",
00126 MXML_INTEGER_CALLBACK);
00127 mxmlLoadString(tree, "<group type='real'>1.0 2.0 3.0</group>",
00128 MXML_REAL_CALLBACK);
00129 mxmlLoadString(tree, "<group>opaque opaque opaque</group>",
00130 MXML_OPAQUE_CALLBACK);
00131 
00132 node = tree->child;
00133 
00134 if (!node)
00135 {
00136 fputs("ERROR: No first child node in basic test!\n", stderr);
00137 mxmlDelete(tree);
00138 return (1);
00139 }
00140 
00141 if (node->type != MXML_INTEGER)
00142 {
00143 fprintf(stderr, "ERROR: First child has type %s (%d), expected MXML_INTEGER!\n",
00144 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00145 "UNKNOWN" : types[node->type], node->type);
00146 mxmlDelete(tree);
00147 return (1);
00148 }
00149 
00150 if (node->value.integer != 123)
00151 {
00152 fprintf(stderr, "ERROR: First child value is %d, expected 123!\n",
00153 node->value.integer);
00154 mxmlDelete(tree);
00155 return (1);
00156 }
00157 
00158 node = node->next;
00159 
00160 if (!node)
00161 {
00162 fputs("ERROR: No second child node in basic test!\n", stderr);
00163 mxmlDelete(tree);
00164 return (1);
00165 }
00166 
00167 if (node->type != MXML_OPAQUE)
00168 {
00169 fprintf(stderr, "ERROR: Second child has type %s (%d), expected MXML_OPAQUE!\n",
00170 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00171 "UNKNOWN" : types[node->type], node->type);
00172 mxmlDelete(tree);
00173 return (1);
00174 }
00175 
00176 if (!node->value.opaque || strcmp(node->value.opaque, "opaque"))
00177 {
00178 fprintf(stderr, "ERROR: Second child value is \"%s\", expected \"opaque\"!\n",
00179 node->value.opaque ? node->value.opaque : "(null)");
00180 mxmlDelete(tree);
00181 return (1);
00182 }
00183 
00184 node = node->next;
00185 
00186 if (!node)
00187 {
00188 fputs("ERROR: No third child node in basic test!\n", stderr);
00189 mxmlDelete(tree);
00190 return (1);
00191 }
00192 
00193 if (node->type != MXML_REAL)
00194 {
00195 fprintf(stderr, "ERROR: Third child has type %s (%d), expected MXML_REAL!\n",
00196 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00197 "UNKNOWN" : types[node->type], node->type);
00198 mxmlDelete(tree);
00199 return (1);
00200 }
00201 
00202 if (node->value.real != 123.4f)
00203 {
00204 fprintf(stderr, "ERROR: Third child value is %f, expected 123.4!\n",
00205 node->value.real);
00206 mxmlDelete(tree);
00207 return (1);
00208 }
00209 
00210 node = node->next;
00211 
00212 if (!node)
00213 {
00214 fputs("ERROR: No fourth child node in basic test!\n", stderr);
00215 mxmlDelete(tree);
00216 return (1);
00217 }
00218 
00219 if (node->type != MXML_TEXT)
00220 {
00221 fprintf(stderr, "ERROR: Fourth child has type %s (%d), expected MXML_TEXT!\n",
00222 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00223 "UNKNOWN" : types[node->type], node->type);
00224 mxmlDelete(tree);
00225 return (1);
00226 }
00227 
00228 if (!node->value.text.whitespace ||
00229 !node->value.text.string || strcmp(node->value.text.string, "text"))
00230 {
00231 fprintf(stderr, "ERROR: Fourth child value is %d,\"%s\", expected 1,\"text\"!\n",
00232 node->value.text.whitespace,
00233 node->value.text.string ? node->value.text.string : "(null)");
00234 mxmlDelete(tree);
00235 return (1);
00236 }
00237 
00238 for (i = 0; i < 4; i ++)
00239 {
00240 node = node->next;
00241 
00242 if (!node)
00243 {
00244 fprintf(stderr, "ERROR: No group #%d child node in basic test!\n", i + 1);
00245 mxmlDelete(tree);
00246 return (1);
00247 }
00248 
00249 if (node->type != MXML_ELEMENT)
00250 {
00251 fprintf(stderr, "ERROR: Group child #%d has type %s (%d), expected MXML_ELEMENT!\n",
00252 i + 1, node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00253 "UNKNOWN" : types[node->type], node->type);
00254 mxmlDelete(tree);
00255 return (1);
00256 }
00257 }
00258 
00259 /*
00260  * Test indices...
00261  */
00262 
00263 ind = mxmlIndexNew(tree, NULL, NULL);
00264 if (!ind)
00265 {
00266 fputs("ERROR: Unable to create index of all nodes!\n", stderr);
00267 mxmlDelete(tree);
00268 return (1);
00269 }
00270 
00271 if (ind->num_nodes != 5)
00272 {
00273 fprintf(stderr, "ERROR: Index of all nodes contains %d "
00274 "nodes; expected 5!\n", ind->num_nodes);
00275 mxmlIndexDelete(ind);
00276 mxmlDelete(tree);
00277 return (1);
00278 }
00279 
00280 mxmlIndexReset(ind);
00281 if (!mxmlIndexFind(ind, "group", NULL))
00282 {
00283 fputs("ERROR: mxmlIndexFind for \"group\" failed!\n", stderr);
00284 mxmlIndexDelete(ind);
00285 mxmlDelete(tree);
00286 return (1);
00287 }
00288 
00289 mxmlIndexDelete(ind);
00290 
00291 ind = mxmlIndexNew(tree, "group", NULL);
00292 if (!ind)
00293 {
00294 fputs("ERROR: Unable to create index of groups!\n", stderr);
00295 mxmlDelete(tree);
00296 return (1);
00297 }
00298 
00299 if (ind->num_nodes != 4)
00300 {
00301 fprintf(stderr, "ERROR: Index of groups contains %d "
00302 "nodes; expected 4!\n", ind->num_nodes);
00303 mxmlIndexDelete(ind);
00304 mxmlDelete(tree);
00305 return (1);
00306 }
00307 
00308 mxmlIndexReset(ind);
00309 if (!mxmlIndexEnum(ind))
00310 {
00311 fputs("ERROR: mxmlIndexEnum failed!\n", stderr);
00312 mxmlIndexDelete(ind);
00313 mxmlDelete(tree);
00314 return (1);
00315 }
00316 
00317 mxmlIndexDelete(ind);
00318 
00319 ind = mxmlIndexNew(tree, NULL, "type");
00320 if (!ind)
00321 {
00322 fputs("ERROR: Unable to create index of type attributes!\n", stderr);
00323 mxmlDelete(tree);
00324 return (1);
00325 }
00326 
00327 if (ind->num_nodes != 3)
00328 {
00329 fprintf(stderr, "ERROR: Index of type attributes contains %d "
00330 "nodes; expected 3!\n", ind->num_nodes);
00331 mxmlIndexDelete(ind);
00332 mxmlDelete(tree);
00333 return (1);
00334 }
00335 
00336 mxmlIndexReset(ind);
00337 if (!mxmlIndexFind(ind, NULL, "string"))
00338 {
00339 fputs("ERROR: mxmlIndexFind for \"string\" failed!\n", stderr);
00340 mxmlIndexDelete(ind);
00341 mxmlDelete(tree);
00342 return (1);
00343 }
00344 
00345 mxmlIndexDelete(ind);
00346 
00347 ind = mxmlIndexNew(tree, "group", "type");
00348 if (!ind)
00349 {
00350 fputs("ERROR: Unable to create index of elements and attributes!\n", stderr);
00351 mxmlDelete(tree);
00352 return (1);
00353 }
00354 
00355 if (ind->num_nodes != 3)
00356 {
00357 fprintf(stderr, "ERROR: Index of elements and attributes contains %d "
00358 "nodes; expected 3!\n", ind->num_nodes);
00359 mxmlIndexDelete(ind);
00360 mxmlDelete(tree);
00361 return (1);
00362 }
00363 
00364 mxmlIndexReset(ind);
00365 if (!mxmlIndexFind(ind, "group", "string"))
00366 {
00367 fputs("ERROR: mxmlIndexFind for \"string\" failed!\n", stderr);
00368 mxmlIndexDelete(ind);
00369 mxmlDelete(tree);
00370 return (1);
00371 }
00372 
00373 mxmlIndexDelete(ind);
00374 
00375 /*
00376  * Check the mxmlDelete() works properly...
00377  */
00378 
00379 for (i = 0; i < 8; i ++)
00380 {
00381 if (tree->child)
00382 mxmlDelete(tree->child);
00383 else
00384 {
00385 fprintf(stderr, "ERROR: Child pointer prematurely NULL on child #%d\n",
00386 i + 1);
00387 mxmlDelete(tree);
00388 return (1);
00389 }
00390 }
00391 
00392 if (tree->child)
00393 {
00394 fputs("ERROR: Child pointer not NULL after deleting all children!\n", stderr);
00395 return (1);
00396 }
00397 
00398 if (tree->last_child)
00399 {
00400 fputs("ERROR: Last child pointer not NULL after deleting all children!\n", stderr);
00401 return (1);
00402 }
00403 
00404 mxmlDelete(tree);
00405 
00406 /*
00407  * Open the file...
00408  */
00409 
00410 if (argv[1][0] == '<')
00411 tree = mxmlLoadString(NULL, argv[1], type_cb);
00412 else if ((fp = fopen(argv[1], "rb")) == NULL)
00413 {
00414 perror(argv[1]);
00415 return (1);
00416 }
00417 else
00418 {
00419 /*
00420  * Read the file...
00421  */
00422 
00423 tree = mxmlLoadFile(NULL, fp, type_cb);
00424 
00425 fclose(fp);
00426 }
00427 
00428 if (!tree)
00429 {
00430 fputs("Unable to read XML file!\n", stderr);
00431 return (1);
00432 }
00433 
00434 if (!strcmp(argv[1], "test.xml"))
00435 {
00436 /*
00437  * Verify that mxmlFindElement() and indirectly mxmlWalkNext() work
00438  * properly...
00439  */
00440 
00441 if ((node = mxmlFindElement(tree, tree, "choice", NULL, NULL,
00442 MXML_DESCEND)) == NULL)
00443 {
00444 fputs("Unable to find first <choice> element in XML tree!\n", stderr);
00445 mxmlDelete(tree);
00446 return (1);
00447 }
00448 
00449 if ((node = mxmlFindElement(node, tree, "choice", NULL, NULL,
00450 MXML_NO_DESCEND)) == NULL)
00451 {
00452 fputs("Unable to find second <choice> element in XML tree!\n", stderr);
00453 mxmlDelete(tree);
00454 return (1);
00455 }
00456 }
00457 
00458 /*
00459  * Print the XML tree...
00460  */
00461 
00462 mxmlSaveFile(tree, stdout, whitespace_cb);
00463 
00464 /*
00465  * Save the XML tree to a string and print it...
00466  */
00467 
00468 if (mxmlSaveString(tree, buffer, sizeof(buffer), whitespace_cb) > 0)
00469 fputs(buffer, stderr);
00470 
00471 /*
00472  * Delete the tree...
00473  */
00474 
00475 mxmlDelete(tree);
00476 
00477 /*
00478  * Read from/write to file descriptors...
00479  */
00480 
00481 if (argv[1][0] != '<')
00482 {
00483 /*
00484  * Open the file again...
00485  */
00486 
00487 if ((fd = open(argv[1], O_RDONLY | O_BINARY)) < 0)
00488 {
00489 perror(argv[1]);
00490 return (1);
00491 }
00492 
00493 /*
00494  * Read the file...
00495  */
00496 
00497 tree = mxmlLoadFd(NULL, fd, type_cb);
00498 
00499 close(fd);
00500 
00501 /*
00502  * Create filename.xmlfd...
00503  */
00504 
00505 snprintf(buffer, sizeof(buffer), "%sfd", argv[1]);
00506 
00507 if ((fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) < 0)
00508 {
00509 perror(buffer);
00510 mxmlDelete(tree);
00511 return (1);
00512 }
00513 
00514 /*
00515  * Write the file...
00516  */
00517 
00518 mxmlSaveFd(tree, fd, whitespace_cb);
00519 
00520 close(fd);
00521 
00522 /*
00523  * Delete the tree...
00524  */
00525 
00526 mxmlDelete(tree);
00527 }
00528 
00529 /*
00530  * Return...
00531  */
00532 
00533 return (0);
00534 }
00535 
00536 
00537 /*
00538  * 'type_cb()' - XML data type callback for mxmlLoadFile()...
00539  */
00540 
00541 mxml_type_t /* O - Data type */
00542 type_cb(mxml_node_t *node) /* I - Element node */
00543 {
00544 const char *type; /* Type string */
00545 
00546 
00547 /*
00548  * You can lookup attributes and/or use the element name, hierarchy, etc...
00549  */
00550 
00551 if ((type = mxmlElementGetAttr(node, "type")) == NULL)
00552 type = node->value.element.name;
00553 
00554 if (!strcmp(type, "integer"))
00555 return (MXML_INTEGER);
00556 else if (!strcmp(type, "opaque") || !strcmp(type, "pre"))
00557 return (MXML_OPAQUE);
00558 else if (!strcmp(type, "real"))
00559 return (MXML_REAL);
00560 else
00561 return (MXML_TEXT);
00562 }
00563 
00564 
00565 /*
00566  * 'whitespace_cb()' - Let the mxmlSaveFile() function know when to insert
00567  * newlines and tabs...
00568  */
00569 
00570 const char * /* O - Whitespace string or NULL */
00571 whitespace_cb(mxml_node_t *node, /* I - Element node */
00572 int where) /* I - Open or close tag? */
00573 {
00574 mxml_node_t *parent; /* Parent node */
00575 int level; /* Indentation level */
00576 const char *name; /* Name of element */
00577 static const char *tabs = "\t\t\t\t\t\t\t\t";
00578 /* Tabs for indentation */
00579 
00580 
00581 /*
00582  * We can conditionally break to a new line before or after any element.
00583  * These are just common HTML elements...
00584  */
00585 
00586 name = node->value.element.name;
00587 
00588 if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
00589 !strcmp(name, "pre") || !strcmp(name, "p") ||
00590 !strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
00591 !strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
00592 {
00593 /*
00594  * Newlines before open and after close...
00595  */
00596 
00597 if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE)
00598 return ("\n");
00599 }
00600 else if (!strcmp(name, "dl") || !strcmp(name, "ol") || !strcmp(name, "ul"))
00601 {
00602 /*
00603  * Put a newline before and after list elements...
00604  */
00605 
00606 return ("\n");
00607 }
00608 else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
00609 {
00610 /*
00611  * Put a tab before <li>'s, <dd>'s, and <dt>'s, and a newline after them...
00612  */
00613 
00614 if (where == MXML_WS_BEFORE_OPEN)
00615 return ("\t");
00616 else if (where == MXML_WS_AFTER_CLOSE)
00617 return ("\n");
00618 }
00619 else if (!strcmp(name, "?xml"))
00620 {
00621 return (NULL);
00622 }
00623 else if (where == MXML_WS_BEFORE_OPEN ||
00624 ((!strcmp(name, "choice") || !strcmp(name, "option")) &&
00625 where == MXML_WS_BEFORE_CLOSE))
00626 {
00627 for (level = -1, parent = node->parent;
00628 parent;
00629 level ++, parent = parent->parent);
00630 
00631 if (level > 8)
00632 level = 8;
00633 else if (level < 0)
00634 level = 0;
00635 
00636 return (tabs + 8 - level);
00637 }
00638 else if (where == MXML_WS_AFTER_CLOSE ||
00639 ((!strcmp(name, "group") || !strcmp(name, "option") ||
00640 !strcmp(name, "choice")) &&
00641 where == MXML_WS_AFTER_OPEN))
00642 return ("\n");
00643 else if (where == MXML_WS_AFTER_OPEN && !node->child)
00644 return ("\n");
00645 
00646 /*
00647  * Return NULL for no added whitespace...
00648  */
00649 
00650 return (NULL);
00651 }
00652 
00653 
00654 /*
00655  * End of "$Id: testmxml.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $".
00656  */

Generated on Tue Oct 28 17:03:22 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /