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
00026
00027
00028
00029
00030
00031
00032
00033 #include "mxml.h"
00034 #ifdef WIN32
00035 # include <io.h>
00036 # include "winconfig.h"
00037 #else
00038 # include <unistd.h>
00039 # include "config.h"
00040 #endif
00041 #include <fcntl.h>
00042 #ifndef O_BINARY
00043 # define O_BINARY 0
00044 #endif
00045
00046
00047
00048
00049
00050
00051 mxml_type_t type_cb(mxml_node_t *node);
00052 const char *whitespace_cb(mxml_node_t *node, int where);
00053
00054
00055
00056
00057
00058
00059 int
00060 main(int argc,
00061 char *argv[])
00062 {
00063 int i;
00064 FILE *fp;
00065 int fd;
00066 mxml_node_t *tree,
00067 *node;
00068 mxml_index_t *ind;
00069 char buffer[16384];
00070 static const char *types[] =
00071 {
00072 "MXML_ELEMENT",
00073 "MXML_INTEGER",
00074 "MXML_OPAQUE",
00075 "MXML_REAL",
00076 "MXML_TEXT"
00077 };
00078
00079
00080
00081
00082
00083
00084 if (argc != 2)
00085 {
00086 fputs("Usage: testmxml filename.xml\n", stderr);
00087 return (1);
00088 }
00089
00090
00091
00092
00093
00094 tree = mxmlNewElement(MXML_NO_PARENT, "element");
00095
00096 if (!tree)
00097 {
00098 fputs("ERROR: No parent node in basic test!\n", stderr);
00099 return (1);
00100 }
00101
00102 if (tree->type != MXML_ELEMENT)
00103 {
00104 fprintf(stderr, "ERROR: Parent has type %s (%d), expected MXML_ELEMENT!\n",
00105 tree->type < MXML_ELEMENT || tree->type > MXML_TEXT ?
00106 "UNKNOWN" : types[tree->type], tree->type);
00107 mxmlDelete(tree);
00108 return (1);
00109 }
00110
00111 if (strcmp(tree->value.element.name, "element"))
00112 {
00113 fprintf(stderr, "ERROR: Parent value is \"%s\", expected \"element\"!\n",
00114 tree->value.element.name);
00115 mxmlDelete(tree);
00116 return (1);
00117 }
00118
00119 mxmlNewInteger(tree, 123);
00120 mxmlNewOpaque(tree, "opaque");
00121 mxmlNewReal(tree, 123.4f);
00122 mxmlNewText(tree, 1, "text");
00123
00124 mxmlLoadString(tree, "<group type='string'>string string string</group>",
00125 MXML_NO_CALLBACK);
00126 mxmlLoadString(tree, "<group type='integer'>1 2 3</group>",
00127 MXML_INTEGER_CALLBACK);
00128 mxmlLoadString(tree, "<group type='real'>1.0 2.0 3.0</group>",
00129 MXML_REAL_CALLBACK);
00130 mxmlLoadString(tree, "<group>opaque opaque opaque</group>",
00131 MXML_OPAQUE_CALLBACK);
00132
00133 node = tree->child;
00134
00135 if (!node)
00136 {
00137 fputs("ERROR: No first child node in basic test!\n", stderr);
00138 mxmlDelete(tree);
00139 return (1);
00140 }
00141
00142 if (node->type != MXML_INTEGER)
00143 {
00144 fprintf(stderr, "ERROR: First child has type %s (%d), expected MXML_INTEGER!\n",
00145 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00146 "UNKNOWN" : types[node->type], node->type);
00147 mxmlDelete(tree);
00148 return (1);
00149 }
00150
00151 if (node->value.integer != 123)
00152 {
00153 fprintf(stderr, "ERROR: First child value is %d, expected 123!\n",
00154 node->value.integer);
00155 mxmlDelete(tree);
00156 return (1);
00157 }
00158
00159 node = node->next;
00160
00161 if (!node)
00162 {
00163 fputs("ERROR: No second child node in basic test!\n", stderr);
00164 mxmlDelete(tree);
00165 return (1);
00166 }
00167
00168 if (node->type != MXML_OPAQUE)
00169 {
00170 fprintf(stderr, "ERROR: Second child has type %s (%d), expected MXML_OPAQUE!\n",
00171 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00172 "UNKNOWN" : types[node->type], node->type);
00173 mxmlDelete(tree);
00174 return (1);
00175 }
00176
00177 if (!node->value.opaque || strcmp(node->value.opaque, "opaque"))
00178 {
00179 fprintf(stderr, "ERROR: Second child value is \"%s\", expected \"opaque\"!\n",
00180 node->value.opaque ? node->value.opaque : "(null)");
00181 mxmlDelete(tree);
00182 return (1);
00183 }
00184
00185 node = node->next;
00186
00187 if (!node)
00188 {
00189 fputs("ERROR: No third child node in basic test!\n", stderr);
00190 mxmlDelete(tree);
00191 return (1);
00192 }
00193
00194 if (node->type != MXML_REAL)
00195 {
00196 fprintf(stderr, "ERROR: Third child has type %s (%d), expected MXML_REAL!\n",
00197 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00198 "UNKNOWN" : types[node->type], node->type);
00199 mxmlDelete(tree);
00200 return (1);
00201 }
00202
00203 if (node->value.real != 123.4f)
00204 {
00205 fprintf(stderr, "ERROR: Third child value is %f, expected 123.4!\n",
00206 node->value.real);
00207 mxmlDelete(tree);
00208 return (1);
00209 }
00210
00211 node = node->next;
00212
00213 if (!node)
00214 {
00215 fputs("ERROR: No fourth child node in basic test!\n", stderr);
00216 mxmlDelete(tree);
00217 return (1);
00218 }
00219
00220 if (node->type != MXML_TEXT)
00221 {
00222 fprintf(stderr, "ERROR: Fourth child has type %s (%d), expected MXML_TEXT!\n",
00223 node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00224 "UNKNOWN" : types[node->type], node->type);
00225 mxmlDelete(tree);
00226 return (1);
00227 }
00228
00229 if (!node->value.text.whitespace ||
00230 !node->value.text.string || strcmp(node->value.text.string, "text"))
00231 {
00232 fprintf(stderr, "ERROR: Fourth child value is %d,\"%s\", expected 1,\"text\"!\n",
00233 node->value.text.whitespace,
00234 node->value.text.string ? node->value.text.string : "(null)");
00235 mxmlDelete(tree);
00236 return (1);
00237 }
00238
00239 for (i = 0; i < 4; i ++)
00240 {
00241 node = node->next;
00242
00243 if (!node)
00244 {
00245 fprintf(stderr, "ERROR: No group #%d child node in basic test!\n", i + 1);
00246 mxmlDelete(tree);
00247 return (1);
00248 }
00249
00250 if (node->type != MXML_ELEMENT)
00251 {
00252 fprintf(stderr, "ERROR: Group child #%d has type %s (%d), expected MXML_ELEMENT!\n",
00253 i + 1, node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
00254 "UNKNOWN" : types[node->type], node->type);
00255 mxmlDelete(tree);
00256 return (1);
00257 }
00258 }
00259
00260
00261
00262
00263
00264 ind = mxmlIndexNew(tree, NULL, NULL);
00265 if (!ind)
00266 {
00267 fputs("ERROR: Unable to create index of all nodes!\n", stderr);
00268 mxmlDelete(tree);
00269 return (1);
00270 }
00271
00272 if (ind->num_nodes != 5)
00273 {
00274 fprintf(stderr, "ERROR: Index of all nodes contains %d "
00275 "nodes; expected 5!\n", ind->num_nodes);
00276 mxmlIndexDelete(ind);
00277 mxmlDelete(tree);
00278 return (1);
00279 }
00280
00281 mxmlIndexReset(ind);
00282 if (!mxmlIndexFind(ind, "group", NULL))
00283 {
00284 fputs("ERROR: mxmlIndexFind for \"group\" failed!\n", stderr);
00285 mxmlIndexDelete(ind);
00286 mxmlDelete(tree);
00287 return (1);
00288 }
00289
00290 mxmlIndexDelete(ind);
00291
00292 ind = mxmlIndexNew(tree, "group", NULL);
00293 if (!ind)
00294 {
00295 fputs("ERROR: Unable to create index of groups!\n", stderr);
00296 mxmlDelete(tree);
00297 return (1);
00298 }
00299
00300 if (ind->num_nodes != 4)
00301 {
00302 fprintf(stderr, "ERROR: Index of groups contains %d "
00303 "nodes; expected 4!\n", ind->num_nodes);
00304 mxmlIndexDelete(ind);
00305 mxmlDelete(tree);
00306 return (1);
00307 }
00308
00309 mxmlIndexReset(ind);
00310 if (!mxmlIndexEnum(ind))
00311 {
00312 fputs("ERROR: mxmlIndexEnum failed!\n", stderr);
00313 mxmlIndexDelete(ind);
00314 mxmlDelete(tree);
00315 return (1);
00316 }
00317
00318 mxmlIndexDelete(ind);
00319
00320 ind = mxmlIndexNew(tree, NULL, "type");
00321 if (!ind)
00322 {
00323 fputs("ERROR: Unable to create index of type attributes!\n", stderr);
00324 mxmlDelete(tree);
00325 return (1);
00326 }
00327
00328 if (ind->num_nodes != 3)
00329 {
00330 fprintf(stderr, "ERROR: Index of type attributes contains %d "
00331 "nodes; expected 3!\n", ind->num_nodes);
00332 mxmlIndexDelete(ind);
00333 mxmlDelete(tree);
00334 return (1);
00335 }
00336
00337 mxmlIndexReset(ind);
00338 if (!mxmlIndexFind(ind, NULL, "string"))
00339 {
00340 fputs("ERROR: mxmlIndexFind for \"string\" failed!\n", stderr);
00341 mxmlIndexDelete(ind);
00342 mxmlDelete(tree);
00343 return (1);
00344 }
00345
00346 mxmlIndexDelete(ind);
00347
00348 ind = mxmlIndexNew(tree, "group", "type");
00349 if (!ind)
00350 {
00351 fputs("ERROR: Unable to create index of elements and attributes!\n", stderr);
00352 mxmlDelete(tree);
00353 return (1);
00354 }
00355
00356 if (ind->num_nodes != 3)
00357 {
00358 fprintf(stderr, "ERROR: Index of elements and attributes contains %d "
00359 "nodes; expected 3!\n", ind->num_nodes);
00360 mxmlIndexDelete(ind);
00361 mxmlDelete(tree);
00362 return (1);
00363 }
00364
00365 mxmlIndexReset(ind);
00366 if (!mxmlIndexFind(ind, "group", "string"))
00367 {
00368 fputs("ERROR: mxmlIndexFind for \"string\" failed!\n", stderr);
00369 mxmlIndexDelete(ind);
00370 mxmlDelete(tree);
00371 return (1);
00372 }
00373
00374 mxmlIndexDelete(ind);
00375
00376
00377
00378
00379
00380 for (i = 0; i < 8; i ++)
00381 {
00382 if (tree->child)
00383 mxmlDelete(tree->child);
00384 else
00385 {
00386 fprintf(stderr, "ERROR: Child pointer prematurely NULL on child #%d\n",
00387 i + 1);
00388 mxmlDelete(tree);
00389 return (1);
00390 }
00391 }
00392
00393 if (tree->child)
00394 {
00395 fputs("ERROR: Child pointer not NULL after deleting all children!\n", stderr);
00396 return (1);
00397 }
00398
00399 if (tree->last_child)
00400 {
00401 fputs("ERROR: Last child pointer not NULL after deleting all children!\n", stderr);
00402 return (1);
00403 }
00404
00405 mxmlDelete(tree);
00406
00407
00408
00409
00410
00411 if (argv[1][0] == '<')
00412 tree = mxmlLoadString(NULL, argv[1], type_cb);
00413 else if ((fp = fopen(argv[1], "rb")) == NULL)
00414 {
00415 perror(argv[1]);
00416 return (1);
00417 }
00418 else
00419 {
00420
00421
00422
00423
00424 tree = mxmlLoadFile(NULL, fp, type_cb);
00425
00426 fclose(fp);
00427 }
00428
00429 if (!tree)
00430 {
00431 fputs("Unable to read XML file!\n", stderr);
00432 return (1);
00433 }
00434
00435 if (!strcmp(argv[1], "test.xml"))
00436 {
00437
00438
00439
00440
00441
00442 if ((node = mxmlFindElement(tree, tree, "choice", NULL, NULL,
00443 MXML_DESCEND)) == NULL)
00444 {
00445 fputs("Unable to find first <choice> element in XML tree!\n", stderr);
00446 mxmlDelete(tree);
00447 return (1);
00448 }
00449
00450 if ((node = mxmlFindElement(node, tree, "choice", NULL, NULL,
00451 MXML_NO_DESCEND)) == NULL)
00452 {
00453 fputs("Unable to find second <choice> element in XML tree!\n", stderr);
00454 mxmlDelete(tree);
00455 return (1);
00456 }
00457 }
00458
00459
00460
00461
00462
00463 mxmlSaveFile(tree, stdout, whitespace_cb);
00464
00465
00466
00467
00468
00469 if (mxmlSaveString(tree, buffer, sizeof(buffer), whitespace_cb) > 0)
00470 fputs(buffer, stderr);
00471
00472
00473
00474
00475
00476 mxmlDelete(tree);
00477
00478
00479
00480
00481
00482 if (argv[1][0] != '<')
00483 {
00484
00485
00486
00487
00488 if ((fd = open(argv[1], O_RDONLY | O_BINARY)) < 0)
00489 {
00490 perror(argv[1]);
00491 return (1);
00492 }
00493
00494
00495
00496
00497
00498 tree = mxmlLoadFd(NULL, fd, type_cb);
00499
00500 close(fd);
00501
00502
00503
00504
00505
00506 snprintf(buffer, sizeof(buffer), "%sfd", argv[1]);
00507
00508 if ((fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) < 0)
00509 {
00510 perror(buffer);
00511 mxmlDelete(tree);
00512 return (1);
00513 }
00514
00515
00516
00517
00518
00519 mxmlSaveFd(tree, fd, whitespace_cb);
00520
00521 close(fd);
00522
00523
00524
00525
00526
00527 mxmlDelete(tree);
00528 }
00529
00530
00531
00532
00533
00534 return (0);
00535 }
00536
00537
00538
00539
00540
00541
00542 mxml_type_t
00543 type_cb(mxml_node_t *node)
00544 {
00545 const char *type;
00546
00547
00548
00549
00550
00551
00552 if ((type = mxmlElementGetAttr(node, "type")) == NULL)
00553 type = node->value.element.name;
00554
00555 if (!strcmp(type, "integer"))
00556 return (MXML_INTEGER);
00557 else if (!strcmp(type, "opaque") || !strcmp(type, "pre"))
00558 return (MXML_OPAQUE);
00559 else if (!strcmp(type, "real"))
00560 return (MXML_REAL);
00561 else
00562 return (MXML_TEXT);
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 const char *
00572 whitespace_cb(mxml_node_t *node,
00573 int where)
00574 {
00575 mxml_node_t *parent;
00576 int level;
00577 const char *name;
00578 static const char *tabs = "\t\t\t\t\t\t\t\t";
00579
00580
00581
00582
00583
00584
00585
00586
00587 name = node->value.element.name;
00588
00589 if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
00590 !strcmp(name, "pre") || !strcmp(name, "p") ||
00591 !strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
00592 !strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
00593 {
00594
00595
00596
00597
00598 if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE)
00599 return ("\n");
00600 }
00601 else if (!strcmp(name, "dl") || !strcmp(name, "ol") || !strcmp(name, "ul"))
00602 {
00603
00604
00605
00606
00607 return ("\n");
00608 }
00609 else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
00610 {
00611
00612
00613
00614
00615 if (where == MXML_WS_BEFORE_OPEN)
00616 return ("\t");
00617 else if (where == MXML_WS_AFTER_CLOSE)
00618 return ("\n");
00619 }
00620 else if (!strcmp(name, "?xml"))
00621 {
00622 return (NULL);
00623 }
00624 else if (where == MXML_WS_BEFORE_OPEN ||
00625 ((!strcmp(name, "choice") || !strcmp(name, "option")) &&
00626 where == MXML_WS_BEFORE_CLOSE))
00627 {
00628 for (level = -1, parent = node->parent;
00629 parent;
00630 level ++, parent = parent->parent);
00631
00632 if (level > 8)
00633 level = 8;
00634 else if (level < 0)
00635 level = 0;
00636
00637 return (tabs + 8 - level);
00638 }
00639 else if (where == MXML_WS_AFTER_CLOSE ||
00640 ((!strcmp(name, "group") || !strcmp(name, "option") ||
00641 !strcmp(name, "choice")) &&
00642 where == MXML_WS_AFTER_OPEN))
00643 return ("\n");
00644 else if (where == MXML_WS_AFTER_OPEN && !node->child)
00645 return ("\n");
00646
00647
00648
00649
00650
00651 return (NULL);
00652 }
00653
00654
00655
00656
00657