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

Generated on Fri Jul 11 17:59:47 2008 for Mobile-C by  doxygen 1.5.4