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 "config.h"
00034 #include "mxml.h"
00035 #ifdef WIN32
00036 # include <io.h>
00037 #else
00038 # include <unistd.h>
00039 #endif
00040 #include <fcntl.h>
00041 #ifndef O_BINARY
00042 # define O_BINARY 0
00043 #endif
00044
00045
00046
00047
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
00056
00057
00058 int
00059 main(int argc,
00060 char *argv[])
00061 {
00062 int i;
00063 FILE *fp;
00064 int fd;
00065 mxml_node_t *tree,
00066 *node;
00067 mxml_index_t *ind;
00068 char buffer[16384];
00069 static const char *types[] =
00070 {
00071 "MXML_ELEMENT",
00072 "MXML_INTEGER",
00073 "MXML_OPAQUE",
00074 "MXML_REAL",
00075 "MXML_TEXT"
00076 };
00077
00078
00079
00080
00081
00082
00083 if (argc != 2)
00084 {
00085 fputs("Usage: testmxml filename.xml\n", stderr);
00086 return (1);
00087 }
00088
00089
00090
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
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
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
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
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
00438
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
00460
00461
00462 mxmlSaveFile(tree, stdout, whitespace_cb);
00463
00464
00465
00466
00467
00468 if (mxmlSaveString(tree, buffer, sizeof(buffer), whitespace_cb) > 0)
00469 fputs(buffer, stderr);
00470
00471
00472
00473
00474
00475 mxmlDelete(tree);
00476
00477
00478
00479
00480
00481 if (argv[1][0] != '<')
00482 {
00483
00484
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
00495
00496
00497 tree = mxmlLoadFd(NULL, fd, type_cb);
00498
00499 close(fd);
00500
00501
00502
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
00516
00517
00518 mxmlSaveFd(tree, fd, whitespace_cb);
00519
00520 close(fd);
00521
00522
00523
00524
00525
00526 mxmlDelete(tree);
00527 }
00528
00529
00530
00531
00532
00533 return (0);
00534 }
00535
00536
00537
00538
00539
00540
00541 mxml_type_t
00542 type_cb(mxml_node_t *node)
00543 {
00544 const char *type;
00545
00546
00547
00548
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
00567
00568
00569
00570 const char *
00571 whitespace_cb(mxml_node_t *node,
00572 int where)
00573 {
00574 mxml_node_t *parent;
00575 int level;
00576 const char *name;
00577 static const char *tabs = "\t\t\t\t\t\t\t\t";
00578
00579
00580
00581
00582
00583
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
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
00604
00605
00606 return ("\n");
00607 }
00608 else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
00609 {
00610
00611
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
00648
00649
00650 return (NULL);
00651 }
00652
00653
00654
00655
00656