/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/mxml-2.2.2/testmxml.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 207 $ : Last Committed Revision
00003  * $Date: 2008-07-11 17:55:19 -0700 (Fri, 11 Jul 2008) $ : 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 Fri Jul 11 17:59:45 2008 for Mobile-C by  doxygen 1.5.4