/home/dko/projects/mobilec/trunk/src/xml_helper.c

Go to the documentation of this file.
00001 /*[
00002  * Copyright (c) 2007 Integration Engineering Laboratory
00003                       University of California, Davis
00004  *
00005  * Permission to use, copy, and distribute this software and its
00006  * documentation for any purpose with or without fee is hereby granted,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.
00010  *
00011  * Permission to modify the software is granted, but not the right to
00012  * distribute the complete modified source code.  Modifications are to
00013  * be distributed as patches to the released version.  Permission to
00014  * distribute binaries produced by compiling modified sources is granted,
00015  * provided you
00016  *   1. distribute the corresponding source modifications from the
00017  *    released version in the form of a patch file along with the binaries,
00018  *   2. add special version identification to distinguish your version
00019  *    in addition to the base release version number,
00020  *   3. provide your name and address as the primary contact for the
00021  *    support of your modified version, and
00022  *   4. retain our contact information in regard to use of the base
00023  *    software.
00024  * Permission to distribute the released version of the source code along
00025  * with corresponding source modifications in the form of a patch file is
00026  * granted with same provisions 2 through 4 for binary distributions.
00027  *
00028  * This software is provided "as is" without express or implied warranty
00029  * to the extent permitted by applicable law.
00030 ]*/
00031 
00032 /* These are xml helper functions.
00033  *
00034  * They were created to ease the switch from libxml2 to mxml.
00035  *
00036  * Written by David Ko <dko@ucdavis.edu> 2006 */
00037 
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <mxml.h>
00042 #include "include/xml_helper.h"
00043 #include "include/macros.h"
00044 
00045 mxml_node_t *
00046 xml_find_sibling(const mxml_node_t *node, const char *sibling_name)
00047 {
00048     if ( !strcmp(
00049                 xml_get_element_name(node),
00050                 sibling_name
00051                 )
00052        ) {
00053         return (mxml_node_t *)node;
00054     } else {
00055         return mxmlFindElement( (mxml_node_t *)node,
00056                 (mxml_node_t *)node->parent,
00057                 sibling_name,
00058                 NULL,
00059                 NULL,
00060                 MXML_NO_DESCEND );
00061     }
00062 }
00063 
00064 /* xml_get_cdata 
00065  * Expects an MXML_ELEMENT with CDATA (returns the data) or a 
00066  * MXML_TEXT node (returns the text). */
00067 char * 
00068 xml_get_cdata(const mxml_node_t *node) {
00069     char *cdata_str;
00070     char *tmp;
00071     const char *buf;
00072     if (node == NULL) {
00073         return NULL;
00074     } else if ( node->type != MXML_ELEMENT) {
00075         return NULL;
00076     }
00077     /* The name of the node should begin with '![CDATA[' and end with ']]' */
00078     buf = xml_get_element_name(node);
00079     cdata_str = (char *)malloc(sizeof(char) * (strlen(buf) + 1));
00080     tmp = strstr(buf, "![CDATA[");
00081     if (tmp == NULL) {
00082         return NULL;
00083     }
00084     tmp = tmp + strlen("![CDATA["); /* Now tmp points to the beginning of the string. */
00085     strcpy(cdata_str, tmp);
00086     for (tmp = cdata_str; *(tmp+2) != '\0'; tmp++) {
00087         if (*tmp == '\0') {
00088             return NULL;
00089         }
00090     }
00091     /* Last two characters must be ']]' */
00092     if ( strcmp(tmp, "]]") ) {
00093         return NULL;
00094     }
00095     CHECK_NULL(tmp, return NULL);
00096     *tmp = '\0';
00097     return cdata_str;
00098 }
00099 
00100 mxml_node_t *
00101 xml_get_child(const mxml_node_t *node, const char *child_name, int descend)
00102 {
00103     return mxmlFindElement( (mxml_node_t *)node,
00104             (mxml_node_t *)node,
00105             child_name,
00106             NULL,
00107             NULL,
00108             descend );
00109 }
00110 
00111 /* Function:  xml_get_deep_child
00112 Arguments: parent: The parent node
00113 child_path: The relative path to the child from the
00114 parent. It is an array of strings terminated
00115 by NULL.
00116 Return Value: A valid xmlNodePtr to the child on success, NULL
00117 on failure.
00118  */
00119     mxml_node_t *
00120 xml_get_deep_child(const mxml_node_t *parent, const char **child_path)
00121 {
00122     int i;
00123     mxml_node_t *node;
00124     node = (mxml_node_t *)parent;
00125     for (i=0; child_path[i] != NULL; i++) {
00126         if ( (node = xml_get_child(node, child_path[i], MXML_NO_DESCEND)) == NULL) {
00127             return NULL;
00128         }
00129     }
00130     return node;
00131 }
00132 
00133 mxml_node_t *
00134 xml_get_next_element(const mxml_node_t *node)
00135 {
00136     node = node->next;
00137     while (node != NULL) {
00138         if (node->type == MXML_ELEMENT) {
00139             break;
00140         }
00141         node = node->next;
00142     }
00143     return (mxml_node_t *)node;
00144 }
00145 
00146 /* Function: xml_get_text
00147    Given a node, it will malloc and return a character string with 
00148    the text of the node. For instance, for a node that looks like
00149    <node> Hello There <\node>
00150    xml_get_text(node_ptr) will return the string "Hello There". */
00151 
00152 char * xml_get_text(const mxml_node_t *node)
00153 {
00154     char *ret;
00155     char *tmp;
00156     mxml_node_t *it; /* iteration temp node */
00157     int len = 0;
00158     if (node->child) {
00159         node = node->child;
00160     } else {
00161         return NULL;
00162     }
00163 
00164     if (node->type == MXML_TEXT || node->type == MXML_ELEMENT) {
00165         /* First, find total string length. */
00166         it = (mxml_node_t *)node;
00167         while (it != NULL && 
00168                     (it->type == MXML_TEXT || it->type == MXML_ELEMENT)
00169               ){
00170             if (it->type == MXML_TEXT) {
00171                 len += strlen(it->value.text.string);
00172                 len++; /*Account for whitespace*/
00173                 it = it->next;
00174             } else if (it->type == MXML_ELEMENT) {
00175                 if ((tmp = strstr(it->value.element.name, "![CDATA["))){
00176                     len += strlen(tmp);
00177                     it = it->next;
00178                 } else {
00179                     break;
00180                 }
00181             } else {
00182                 break;
00183             }
00184         }
00185     } else {
00186         return NULL;
00187     }
00188     ret = malloc( sizeof(char) * (len + 1));
00189     *ret = '\0';
00190     for ( 
00191             it = (mxml_node_t *)node; 
00192             it != NULL && (it->type == MXML_TEXT || it->type == MXML_ELEMENT); 
00193             it = it->next) {
00194         if (it->type == MXML_TEXT) {
00195             if (it->value.text.whitespace == 1) {
00196                 strcat(ret, " ");
00197             } 
00198             strcat(ret, it->value.text.string);
00199         } else if (it->type == MXML_ELEMENT) {
00200             if ((tmp = xml_get_cdata(it))) {
00201 /*                strcat(ret, " "); */
00202                 strcat(ret, tmp);
00203                 free(tmp);
00204             } else {
00205                 break;
00206             }
00207         } else { /* Should never get here */
00208             CHECK_NULL( NULL, exit(0) );
00209         }
00210     }
00211     return ret;
00212 }
00213 
00214 const char* xml_get_element_name(const mxml_node_t *node)
00215 {
00216     if (node->type != MXML_ELEMENT) {
00217         return NULL;
00218     } else {
00219         return node->value.element.name;
00220     }
00221 }
00222 
00223 /* xml_new_cdata
00224  *
00225  * Creates a new cdata node under 'parent'. */
00226 mxml_node_t *
00227 xml_new_cdata(mxml_node_t* parent, const char* text) {
00228     char *tmp;
00229     int namelen;
00230     mxml_node_t * node;
00231     namelen = (strlen(text) + strlen("![CDATA[]]")+1) * sizeof(char);
00232     tmp = (char*)malloc(namelen);
00233     CHECK_NULL(tmp, exit(0) );
00234     *tmp = '\0';
00235     strcat(tmp, "![CDATA[");
00236     strcat(tmp, text);
00237     strcat(tmp, "]]");
00238     node = mxmlNewElement(
00239             parent,
00240             (const char*)tmp );
00241     free((char*)tmp); 
00242     return node;
00243 }
00244 /* This is a simple whitespace callback for mxml */
00245     const char* 
00246 whitespace_cb( mxml_node_t *node, 
00247         int where ) 
00248 {
00249     if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE) {
00250         return("\n");
00251     } else {
00252         return NULL;
00253     }
00254 }

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4