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