Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

wbxml_tree.c

Go to the documentation of this file.
00001 /*
00002  * WBXML Lib, the WBXML Library.
00003  * Copyright (C) 2002-2003  Aymerick Jéhanne
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License (version 2.1) as published by the Free Software Foundation.
00008  * 
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  *
00018  * LGPL v2.1: http://www.gnu.org/licenses/lgpl.txt
00019  *
00020  * Author Contact: libwbxml@jehanne.org
00021  * WBXML Lib home: http://libwbxml.jehanne.org
00022  */
00023  
00034 #include <string.h> /* For strcmp() */
00035 
00036 #include "wbxml.h"
00037 
00038 
00039 /***************************************************
00040  *    Public Functions
00041  */
00042 
00043 /* WBXML Tree Building Functions */
00044 
00045 WBXML_DECLARE(WBXMLError) wbxml_tree_from_wbxml(WB_UTINY *wbxml, WB_ULONG wbxml_len, WBXMLLanguage lang, WBXMLTree **tree)
00046 {   
00047     WBXMLParser *wbxml_parser = NULL;
00048     WB_LONG error_index = 0;
00049     WBXMLTreeClbCtx wbxml_tree_clb_ctx;
00050     WBXMLError ret = WBXML_OK;
00051     WBXMLContentHandler wbxml_tree_content_handler = 
00052         {
00053             wbxml_tree_clb_wbxml_start_document,
00054             wbxml_tree_clb_wbxml_end_document,
00055             wbxml_tree_clb_wbxml_start_element,
00056             wbxml_tree_clb_wbxml_end_element,
00057             wbxml_tree_clb_wbxml_characters,
00058             wbxml_tree_clb_wbxml_pi
00059         };
00060 
00061     if (tree != NULL)
00062         *tree = NULL;
00063 
00064     /* Create WBXML Parser */
00065     if((wbxml_parser = wbxml_parser_create()) == NULL) {
00066         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Parser"));
00067         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00068     }
00069 
00070     /* Init context */
00071     wbxml_tree_clb_ctx.error = WBXML_OK;
00072     wbxml_tree_clb_ctx.current = NULL;
00073     if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create()) == NULL) {
00074         wbxml_parser_destroy(wbxml_parser);
00075         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
00076         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00077     }
00078     
00079     /* Set Handlers Callbacks */
00080     wbxml_parser_set_user_data(wbxml_parser, &wbxml_tree_clb_ctx);
00081     wbxml_parser_set_content_handler(wbxml_parser, &wbxml_tree_content_handler);
00082 
00083     /* Give the user the possibility to force Document Language */
00084     if (lang != WBXML_LANG_UNKNOWN)
00085         wbxml_parser_set_language(wbxml_parser, lang);
00086 
00087     /* Parse the WBXML document to WBXML Tree */
00088     ret = wbxml_parser_parse(wbxml_parser, wbxml, wbxml_len);
00089     if ((ret != WBXML_OK) || (wbxml_tree_clb_ctx.error != WBXML_OK)) 
00090     {
00091         error_index = wbxml_parser_get_current_byte_index(wbxml_parser);
00092         WBXML_ERROR((WBXML_PARSER, "WBXML Parser failed at %ld - token: %x (%s)", 
00093                                    error_index,
00094                                    wbxml[error_index],
00095                                    ret != WBXML_OK ? wbxml_errors_string(ret) : wbxml_errors_string(wbxml_tree_clb_ctx.error)));
00096         
00097         wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
00098     }
00099     else {
00100         *tree = wbxml_tree_clb_ctx.tree;
00101     }
00102 
00103     /* Clean-up */
00104     wbxml_parser_destroy(wbxml_parser);
00105 
00106     if (ret != WBXML_OK)
00107         return ret;
00108     else
00109         return wbxml_tree_clb_ctx.error;
00110 }
00111 
00112 
00113 WBXML_DECLARE(WBXMLError) wbxml_tree_from_xml(WB_UTINY *xml, WBXMLTree **tree)
00114 {
00115 #if !defined( HAVE_EXPAT )
00116 
00117     return WBXML_ERROR_NO_XMLPARSER;
00118 
00119 #else /* HAVE_EXPAT */
00120 
00121     XML_Parser xml_parser = NULL;
00122     WBXMLTreeClbCtx wbxml_tree_clb_ctx;
00123     WBXMLError ret = WBXML_OK;
00124 
00125     if (tree != NULL)
00126         *tree = NULL;
00127 
00128     /* Create XML Parser */
00129     if ((xml_parser = XML_ParserCreate(NULL)) == NULL)
00130         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00131     
00132     /* Init context */
00133     wbxml_tree_clb_ctx.current = NULL;
00134     wbxml_tree_clb_ctx.error = WBXML_OK;
00135     wbxml_tree_clb_ctx.skip_lvl = 0;
00136     wbxml_tree_clb_ctx.skip_start = 0;
00137     wbxml_tree_clb_ctx.xml_parser = xml_parser;
00138     wbxml_tree_clb_ctx.input_buff = xml;    
00139 
00140     if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create()) == NULL) {
00141         XML_ParserFree(xml_parser);
00142         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
00143         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
00144     }
00145     
00146     /* Set Handlers Callbacks */
00147     XML_SetStartDoctypeDeclHandler(xml_parser, wbxml_tree_clb_xml_doctype_decl);
00148     XML_SetElementHandler(xml_parser, wbxml_tree_clb_xml_start_element, wbxml_tree_clb_xml_end_element);
00149         XML_SetCdataSectionHandler(xml_parser, wbxml_tree_clb_xml_start_cdata, wbxml_tree_clb_xml_end_cdata);
00150         XML_SetProcessingInstructionHandler(xml_parser , wbxml_tree_clb_xml_pi);
00151     XML_SetCharacterDataHandler(xml_parser, wbxml_tree_clb_xml_characters);
00152     XML_SetUserData(xml_parser, (void*)&wbxml_tree_clb_ctx);
00153 
00154     /* Parse the XML Document to WBXML Tree */
00155     if (XML_Parse(xml_parser, (WB_TINY*) xml, WBXML_STRLEN(xml), TRUE) == 0)
00156     {
00157         WBXML_ERROR((WBXML_CONV, "xml2wbxml convertion failed - expat error %i\n"
00158             "\tdescription: %s\n"
00159             "\tline: %i\n"
00160             "\tcolumn: %i\n"
00161             "\tbyte index: %i\n"
00162             "\ttotal bytes: %i\n%s",
00163             XML_GetErrorCode(xml_parser), 
00164             XML_ErrorString(XML_GetErrorCode(xml_parser)), 
00165             XML_GetCurrentLineNumber(xml_parser), 
00166             XML_GetCurrentColumnNumber(xml_parser), 
00167             XML_GetCurrentByteIndex(xml_parser), 
00168             XML_GetCurrentByteCount(xml_parser), xml));
00169 
00170         wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
00171 
00172         ret = WBXML_ERROR_XML_PARSING_FAILED;
00173     }
00174     else {
00175         if ((ret = wbxml_tree_clb_ctx.error) != WBXML_OK)
00176             wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
00177         else
00178             *tree = wbxml_tree_clb_ctx.tree;
00179     }
00180 
00181     /* Clean-up */
00182     XML_ParserFree(xml_parser);
00183 
00184     return ret;
00185 
00186 #endif /* HAVE_EXPAT */
00187 }
00188 
00189 
00190 /* WBXMLTreeAttribute */
00191 
00192 WBXML_DECLARE(WBXMLTreeAttribute *) wbxml_tree_attribute_create(void)
00193 {
00194     WBXMLTreeAttribute *result = NULL;
00195     
00196     if ((result = (WBXMLTreeAttribute *) wbxml_malloc(sizeof(WBXMLTreeAttribute))) == NULL)
00197         return NULL;
00198 
00199     result->attr = NULL;
00200     result->next = NULL;
00201 
00202     return result;
00203 }
00204 
00205 
00206 WBXML_DECLARE(void) wbxml_tree_attribute_destroy(WBXMLTreeAttribute *attr)
00207 {
00208     WBXMLTreeAttribute *next = NULL;
00209 
00210     while (attr != NULL) 
00211     {
00212         next = attr->next;
00213 
00214         wbxml_attribute_destroy(attr->attr);   
00215         wbxml_free(attr);
00216 
00217         attr = next;
00218     }
00219 }
00220 
00221 
00222 /* WBXMLTreeNode */
00223 
00224 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create(WBXMLTreeNodeType type)
00225 {
00226     WBXMLTreeNode *result = NULL;
00227     
00228     if ((result = (WBXMLTreeNode *) wbxml_malloc(sizeof(WBXMLTreeNode))) == NULL)
00229         return NULL;
00230 
00231     result->type = type;
00232     result->name = NULL;
00233     result->attrs = NULL;
00234     result->content = NULL;
00235     result->tree = NULL;
00236 
00237     result->parent = NULL;
00238     result->children = NULL;
00239     result->next = NULL;
00240     result->prev = NULL;
00241 
00242     return result;
00243 }
00244 
00245 
00246 WBXML_DECLARE(void) wbxml_tree_node_destroy(WBXMLTreeNode *node)
00247 {
00248     if (node == NULL)
00249         return;
00250 
00251     wbxml_tag_destroy(node->name);
00252     wbxml_tree_attribute_destroy(node->attrs);
00253     wbxml_buffer_destroy(node->content);
00254     wbxml_tree_destroy(node->tree);
00255 
00256     wbxml_free(node);
00257 }
00258 
00259 
00260 /* WBXMLTree */
00261 
00262 WBXML_DECLARE(WBXMLTree *) wbxml_tree_create(void)
00263 {
00264     WBXMLTree *result = NULL;
00265     
00266     if ((result = (WBXMLTree *) wbxml_malloc(sizeof(WBXMLTree))) == NULL)
00267         return NULL;
00268 
00269     result->lang = NULL;
00270     result->root = NULL;
00271 
00272     return result;
00273 }
00274 
00275 
00276 WBXML_DECLARE(void) wbxml_tree_destroy(WBXMLTree *tree)
00277 {
00278     WBXMLTreeNode *current_node = NULL, *previous_node = NULL, *tmp_node = NULL;
00279     WB_BOOL end_of_walk= FALSE;
00280 
00281     if (tree == NULL)
00282         return;
00283 
00284         /* Let's go through the tree (iteratively) to free all the nodes */
00285         current_node = tree->root;
00286 
00287         while (!end_of_walk)
00288     {
00289                 if (current_node == NULL) {
00290                         if (previous_node == NULL) {
00291                                 end_of_walk = TRUE;
00292                                 break;
00293                         }
00294                         else {
00295                                 if (previous_node->parent == NULL) {
00296                                         /* End of parsing, we have parsed the last child of root node */
00297                                         end_of_walk = TRUE;
00298                                         break;
00299                                 }
00300                                 else {
00301                                         /* Let's parse next child of parent element */                                  
00302                                         current_node = previous_node->next;
00303                                         tmp_node = previous_node->parent;
00304 
00305                                         /* Destroy this node (leaf) */
00306                                         wbxml_tree_node_destroy(previous_node);
00307 
00308                                         previous_node = tmp_node;
00309                                 }
00310                         }
00311                 }
00312                 else {
00313                         previous_node = current_node;
00314                         current_node = current_node->children;          
00315                 }
00316         }
00317 
00318     wbxml_tree_node_destroy(tree->root);
00319     wbxml_free(tree);
00320 }
00321 
00322 
00323 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_get_element_node_from_name(WBXMLTreeNode *node, const char *name, WB_BOOL recurs)
00324 {
00325     WBXMLTreeNode *current_node = NULL;
00326     WB_BOOL node_found = FALSE;
00327 
00328     if ((node == NULL) || (name == NULL))
00329         return NULL;
00330 
00333         /* Let's go through the tree */
00334         current_node = node;
00335 
00336         while (current_node != NULL)
00337     {
00338                 /* Is this the Node we searched ? */
00339         if ((current_node->type == WBXML_TREE_ELEMENT_NODE) && 
00340             (WBXML_STRCMP(wbxml_tag_get_xml_name(current_node->name), name) == 0))
00341         {
00342             node_found = TRUE;
00343             break;
00344         }
00345         else {
00346             /* Go to next Sibbling Node */
00347             current_node = current_node->next;
00348         }
00349         }
00350 
00351     if (node_found)
00352         return current_node;
00353 
00354     return NULL;
00355 }

Generated on Mon Nov 24 20:09:43 2003 for WBXML Library by doxygen1.3-rc1