📄 wbxml_tree.c
字号:
/* * libwbxml, the WBXML Library. * Copyright (C) 2002-2005 Aymerick Jehanne <aymerick@jehanne.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * LGPL v2.1: http://www.gnu.org/copyleft/lesser.txt * * Contact: libwbxml@aymerick.com * Home: http://libwbxml.aymerick.com */ /** * @file wbxml_tree.c * @ingroup wbxml_tree * * @author Aymerick Jehanne <libwbxml@aymerick.com> * @date 03/02/18 * * @brief WBXML Tree */#include "wbxml.h"/*************************************************** * Public Functions */WBXML_DECLARE(WBXMLError) wbxml_tree_from_wbxml(WB_UTINY *wbxml, WB_ULONG wbxml_len, WBXMLLanguage lang, WBXMLTree **tree){ WBXMLParser *wbxml_parser = NULL; WB_LONG error_index = 0; WBXMLTreeClbCtx wbxml_tree_clb_ctx; WBXMLError ret = WBXML_OK; WBXMLContentHandler wbxml_tree_content_handler = { wbxml_tree_clb_wbxml_start_document, wbxml_tree_clb_wbxml_end_document, wbxml_tree_clb_wbxml_start_element, wbxml_tree_clb_wbxml_end_element, wbxml_tree_clb_wbxml_characters, wbxml_tree_clb_wbxml_pi }; if (tree != NULL) *tree = NULL; /* Create WBXML Parser */ if((wbxml_parser = wbxml_parser_create()) == NULL) { WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Parser")); return WBXML_ERROR_NOT_ENOUGH_MEMORY; } /* Init context */ wbxml_tree_clb_ctx.error = WBXML_OK; wbxml_tree_clb_ctx.current = NULL; if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) { wbxml_parser_destroy(wbxml_parser); WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree")); return WBXML_ERROR_NOT_ENOUGH_MEMORY; } /* Set Handlers Callbacks */ wbxml_parser_set_user_data(wbxml_parser, &wbxml_tree_clb_ctx); wbxml_parser_set_content_handler(wbxml_parser, &wbxml_tree_content_handler); /* Give the user the possibility to force Document Language */ if (lang != WBXML_LANG_UNKNOWN) wbxml_parser_set_language(wbxml_parser, lang); /** @todo Use wbxml_parser_set_meta_charset() */ /* Parse the WBXML document to WBXML Tree */ ret = wbxml_parser_parse(wbxml_parser, wbxml, wbxml_len); if ((ret != WBXML_OK) || (wbxml_tree_clb_ctx.error != WBXML_OK)) { error_index = wbxml_parser_get_current_byte_index(wbxml_parser); WBXML_ERROR((WBXML_PARSER, "WBXML Parser failed at %ld - token: %x (%s)", error_index, wbxml[error_index], ret != WBXML_OK ? wbxml_errors_string(ret) : wbxml_errors_string(wbxml_tree_clb_ctx.error))); wbxml_tree_destroy(wbxml_tree_clb_ctx.tree); } else { *tree = wbxml_tree_clb_ctx.tree; } /* Clean-up */ wbxml_parser_destroy(wbxml_parser); if (ret != WBXML_OK) return ret; else return wbxml_tree_clb_ctx.error;}WBXML_DECLARE(WBXMLError) wbxml_tree_to_wbxml(WBXMLTree *tree, WB_UTINY **wbxml, WB_ULONG *wbxml_len, WBXMLGenWBXMLParams *params){ WBXMLEncoder *wbxml_encoder = NULL; WBXMLError ret = WBXML_OK; /* Encode WBXML Tree to WBXML Document */ if ((wbxml_encoder = wbxml_encoder_create()) == NULL) { return WBXML_ERROR_NOT_ENOUGH_MEMORY; } /* Set the WBXML Tree to encode */ wbxml_encoder_set_tree(wbxml_encoder, tree); /* Set encoder parameters */ if (params == NULL) { /* Default Parameters */ /* Ignores "Empty Text" Nodes */ wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE); /* Remove leading and trailing whitespaces in "Text Nodes" */ wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE); /* Use String Table */ wbxml_encoder_set_use_strtbl(wbxml_encoder, TRUE); } else { /* WBXML Version */ wbxml_encoder_set_wbxml_version(wbxml_encoder, params->wbxml_version); /* Keep Ignorable Whitespaces ? */ if (!params->keep_ignorable_ws) { /* Ignores "Empty Text" Nodes */ wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE); /* Remove leading and trailing whitespaces in "Text Nodes" */ wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE); } /* String Table */ wbxml_encoder_set_use_strtbl(wbxml_encoder, params->use_strtbl); /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */ } /* Encode WBXML */ ret = wbxml_encoder_encode_to_wbxml(wbxml_encoder, wbxml, wbxml_len); /* Clean-up */ wbxml_encoder_destroy(wbxml_encoder); return ret;}WBXML_DECLARE(WBXMLError) wbxml_tree_from_xml(WB_UTINY *xml, WB_ULONG xml_len, WBXMLTree **tree){#if defined( HAVE_EXPAT ) const XML_Feature *feature_list = NULL; XML_Parser xml_parser = NULL; WBXMLError ret = WBXML_OK; WB_BOOL expat_utf16 = FALSE; WBXMLTreeClbCtx wbxml_tree_clb_ctx; /* First Check if Expat is outputing UTF-16 strings */ feature_list = (const XML_Feature *)XML_GetFeatureList(); if ((feature_list != NULL) && (feature_list[0].value != sizeof(WB_TINY))) {#if !defined( HAVE_ICONV ) /* Ouch, can't convert from UTF-16 to UTF-8 */ return WBXML_ERROR_XMLPARSER_OUTPUT_UTF16;#else /* Expat returns UTF-16 encoded strings in its callbacks */ expat_utf16 = TRUE;#endif /* !HAVE_ICONV */ } if (tree != NULL) *tree = NULL; /* Create Expat XML Parser */ if ((xml_parser = XML_ParserCreate(NULL)) == NULL) return WBXML_ERROR_NOT_ENOUGH_MEMORY; /* Init context */ wbxml_tree_clb_ctx.current = NULL; wbxml_tree_clb_ctx.error = WBXML_OK; wbxml_tree_clb_ctx.skip_lvl = 0; wbxml_tree_clb_ctx.skip_start = 0; wbxml_tree_clb_ctx.xml_parser = xml_parser; wbxml_tree_clb_ctx.input_buff = xml; wbxml_tree_clb_ctx.expat_utf16 = expat_utf16; /* Create WBXML Tree */ if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) { XML_ParserFree(xml_parser); WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree")); return WBXML_ERROR_NOT_ENOUGH_MEMORY; } /* Set Handlers Callbacks */ XML_SetXmlDeclHandler(xml_parser, wbxml_tree_clb_xml_decl); XML_SetStartDoctypeDeclHandler(xml_parser, wbxml_tree_clb_xml_doctype_decl); XML_SetElementHandler(xml_parser, wbxml_tree_clb_xml_start_element, wbxml_tree_clb_xml_end_element); XML_SetCdataSectionHandler(xml_parser, wbxml_tree_clb_xml_start_cdata, wbxml_tree_clb_xml_end_cdata); XML_SetProcessingInstructionHandler(xml_parser , wbxml_tree_clb_xml_pi); XML_SetCharacterDataHandler(xml_parser, wbxml_tree_clb_xml_characters); XML_SetUserData(xml_parser, (void*)&wbxml_tree_clb_ctx); /* Parse the XML Document to WBXML Tree */ if (XML_Parse(xml_parser, (WB_TINY*) xml, xml_len, TRUE) == 0) { WBXML_ERROR((WBXML_CONV, "xml2wbxml convertion failed - expat error %i\n" "\tdescription: %s\n" "\tline: %i\n" "\tcolumn: %i\n" "\tbyte index: %i\n" "\ttotal bytes: %i\n%s", XML_GetErrorCode(xml_parser), XML_ErrorString(XML_GetErrorCode(xml_parser)), XML_GetCurrentLineNumber(xml_parser), XML_GetCurrentColumnNumber(xml_parser), XML_GetCurrentByteIndex(xml_parser), XML_GetCurrentByteCount(xml_parser), xml)); wbxml_tree_destroy(wbxml_tree_clb_ctx.tree); ret = WBXML_ERROR_XML_PARSING_FAILED; } else { if ((ret = wbxml_tree_clb_ctx.error) != WBXML_OK) wbxml_tree_destroy(wbxml_tree_clb_ctx.tree); else *tree = wbxml_tree_clb_ctx.tree; } /* Clean-up */ XML_ParserFree(xml_parser); return ret;#else /* HAVE_EXPAT */#if defined( HAVE_LIBXML ) /** @todo Use LibXML2 SAX interface ! */ return WBXML_ERROR_NO_XMLPARSER;#else /* HAVE_LIBXML */ /** @note You can add here another XML Parser support */ return WBXML_ERROR_NO_XMLPARSER;#endif /* HAVE_LIBXML */#endif /* HAVE_EXPAT */}WBXML_DECLARE(WBXMLError) wbxml_tree_to_xml(WBXMLTree *tree, WB_UTINY **xml, WB_ULONG *xml_len, WBXMLGenXMLParams *params){ WBXMLEncoder *wbxml_encoder = NULL; WBXMLError ret = WBXML_OK; /* Create WBXML Encoder */ if ((wbxml_encoder = wbxml_encoder_create()) == NULL) { return WBXML_ERROR_NOT_ENOUGH_MEMORY; } /* Set the WBXML Tree to encode */ wbxml_encoder_set_tree(wbxml_encoder, tree); /* Set encoder parameters */ if (params == NULL) { /* Default Values */ /* Set XML Generation Type */ wbxml_encoder_set_xml_gen_type(wbxml_encoder, WBXML_GEN_XML_INDENT); /* Set Indent */ wbxml_encoder_set_indent(wbxml_encoder, 0); /* Skip Ignorable Whitespaces */ wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE); wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE); } else { /* Set XML Generation Type */ wbxml_encoder_set_xml_gen_type(wbxml_encoder, params->gen_type); /* Set Indent */ if (params->gen_type == WBXML_GEN_XML_INDENT) wbxml_encoder_set_indent(wbxml_encoder, params->indent); /* Ignorable Whitespaces */ if (params->keep_ignorable_ws) { wbxml_encoder_set_ignore_empty_text(wbxml_encoder, FALSE); wbxml_encoder_set_remove_text_blanks(wbxml_encoder, FALSE); } else { wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE); wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE); } /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */ } /* Encode WBXML Tree to XML */ ret = wbxml_encoder_encode_tree_to_xml(wbxml_encoder, xml, xml_len); /* Clean-up */ wbxml_encoder_destroy(wbxml_encoder); return ret;}#if defined( HAVE_LIBXML )WBXML_DECLARE(WBXMLError) wbxml_tree_from_libxml_doc(xmlDocPtr libxml_doc, WBXMLTree **tree){ /** @todo wbxml_tree_from_libxml_doc() */ return WBXML_ERROR_NOT_IMPLEMENTED;}WBXML_DECLARE(WBXMLError) wbxml_tree_to_libxml_doc(WBXMLTree *tree, xmlDocPtr *libxml_doc){ /** @todo wbxml_tree_to_libxml_doc() */ return WBXML_ERROR_NOT_IMPLEMENTED;}#endif /* HAVE_LIBXML */WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create(WBXMLTreeNodeType type){ WBXMLTreeNode *result = NULL; if ((result = (WBXMLTreeNode *) wbxml_malloc(sizeof(WBXMLTreeNode))) == NULL) return NULL; result->type = type; result->name = NULL; result->attrs = NULL; result->content = NULL; result->tree = NULL; result->parent = NULL; result->children = NULL; result->next = NULL; result->prev = NULL; return result;}WBXML_DECLARE(void) wbxml_tree_node_destroy(WBXMLTreeNode *node){ if (node == NULL) return; wbxml_tag_destroy(node->name); wbxml_list_destroy(node->attrs, wbxml_attribute_destroy_item); wbxml_buffer_destroy(node->content); wbxml_tree_destroy(node->tree); wbxml_free(node);}WBXML_DECLARE(void) wbxml_tree_node_destroy_item(void *node){ wbxml_tree_node_destroy((WBXMLTreeNode *)node);}WBXML_DECLARE(void) wbxml_tree_node_destroy_all(WBXMLTreeNode *node){ WBXMLTreeNode *parent_node = NULL; WBXMLTreeNode *current_node = NULL; WBXMLTreeNode *previous_node = NULL; WBXMLTreeNode *tmp_node = NULL; WB_BOOL end_of_walk = FALSE; if (node == NULL) return; /* Let's go through the sub-tree (iteratively) to free all the nodes */ current_node = node; parent_node = node->parent; while (!end_of_walk) { if (current_node == NULL) { /* Leaf reached */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -