00001 /* SVN FILE INFO 00002 * $Revision: 174 $ : Last Committed Revision 00003 * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月24日) $ : 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 }