📄 xml_element.c
字号:
/* This file is part of libXMLRPC - a C library for xml-encoded function calls. Author: Dan Libby (dan@libby.com) Epinions.com may be contacted at feedback@epinions-inc.com*//* Copyright 2000 Epinions, Inc. Subject to the following 3 conditions, Epinions, Inc. permits you, free of charge, to (a) use, copy, distribute, modify, perform and display this software and associated documentation files (the "Software"), and (b) permit others to whom the Software is furnished to do so as well. 1) The above copyright notice and this permission notice shall be included without modification in all copies or substantial portions of the Software. 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. */static const char rcsid[] = "#(@) $Id: xml_element.c,v 1.10 2006/07/30 11:33:49 tony2001 Exp $";/****h* ABOUT/xml_element * NAME * xml_element * AUTHOR * Dan Libby, aka danda (dan@libby.com) * CREATION DATE * 06/2000 * HISTORY * $Log: xml_element.c,v $ * Revision 1.10 2006/07/30 11:33:49 tony2001 * fix compile warnings (#38257) * * Revision 1.9 2005/04/22 11:06:53 jorton * Fixed bug #32797 (invalid C code in xmlrpc extension). * * Revision 1.8 2005/03/28 00:07:24 edink * Reshufle includes to make it compile on windows * * Revision 1.7 2005/03/26 03:13:58 sniper * - Made it possible to build ext/xmlrpc with libxml2 * * Revision 1.6 2004/06/01 20:16:06 iliaa * Fixed bug #28597 (xmlrpc_encode_request() incorrectly encodes chars in * 200-210 range). * Patch by: fernando dot nemec at folha dot com dot br * * Revision 1.5 2003/12/16 21:00:21 sniper * Fix some compile warnings (patch by Joe Orton) * * Revision 1.4 2002/11/26 23:01:16 fmk * removing unused variables * * Revision 1.3 2002/07/05 04:43:53 danda * merged in updates from SF project. bring php repository up to date with xmlrpc-epi version 0.51 * * Revision 1.9 2002/07/03 20:54:30 danda * root element should not have a parent. patch from anon SF user * * Revision 1.8 2002/05/23 17:46:51 danda * patch from mukund - fix non utf-8 encoding conversions * * Revision 1.7 2002/02/13 20:58:50 danda * patch to make source more windows friendly, contributed by Jeff Lawson * * Revision 1.6 2002/01/08 01:06:55 danda * enable <?xml version="1.0"?> format for parsers that are very picky. * * Revision 1.5 2001/09/29 21:58:05 danda * adding cvs log to history section * * 10/15/2000 -- danda -- adding robodoc documentation * TODO * Nicer external API. Get rid of macros. Make opaque types, etc. * PORTABILITY * Coded on RedHat Linux 6.2. Builds on Solaris x86. Should build on just * about anything with minor mods. * NOTES * This code incorporates ideas from expat-ensor from http://xml.ensor.org. * * It was coded primarily to act as a go-between for expat and xmlrpc. To this * end, it stores xml elements, their sub-elements, and their attributes in an * in-memory tree. When expat is done parsing, the tree can be walked, thus * retrieving the values. The code can also be used to build a tree via API then * write out the tree to a buffer, thus "serializing" the xml. * * It turns out this is useful for other purposes, such as parsing config files. * YMMV. * * Some Features: * - output option for xml escaping data. Choices include no escaping, entity escaping, * or CDATA sections. * - output option for character encoding. Defaults to (none) utf-8. * - output option for verbosity/readability. ultra-compact, newlines, pretty/level indented. * * BUGS * there must be some. ******/ #include "ext/xml/expat_compat.h"#ifdef _WIN32#include "xmlrpc_win32.h"#endif#include <stdlib.h>#include <string.h>#include <ctype.h>#include "xml_element.h"#include "queue.h"#include "encodings.h"#define my_free(thing) if(thing) {free(thing); thing = NULL;}#define XML_DECL_START "<?xml"#define XML_DECL_START_LEN sizeof(XML_DECL_START) - 1#define XML_DECL_VERSION "version=\"1.0\""#define XML_DECL_VERSION_LEN sizeof(XML_DECL_VERSION) - 1#define XML_DECL_ENCODING_ATTR "encoding"#define XML_DECL_ENCODING_ATTR_LEN sizeof(XML_DECL_ENCODING_ATTR) - 1#define XML_DECL_ENCODING_DEFAULT "utf-8"#define XML_DECL_ENCODING_DEFAULT_LEN sizeof(XML_DECL_ENCODING_DEFAULT) - 1#define XML_DECL_END "?>"#define XML_DECL_END_LEN sizeof(XML_DECL_END) - 1#define START_TOKEN_BEGIN "<"#define START_TOKEN_BEGIN_LEN sizeof(START_TOKEN_BEGIN) - 1#define START_TOKEN_END ">"#define START_TOKEN_END_LEN sizeof(START_TOKEN_END) - 1#define EMPTY_START_TOKEN_END "/>"#define EMPTY_START_TOKEN_END_LEN sizeof(EMPTY_START_TOKEN_END) - 1#define END_TOKEN_BEGIN "</"#define END_TOKEN_BEGIN_LEN sizeof(END_TOKEN_BEGIN) - 1#define END_TOKEN_END ">"#define END_TOKEN_END_LEN sizeof(END_TOKEN_END) - 1#define ATTR_DELIMITER "\""#define ATTR_DELIMITER_LEN sizeof(ATTR_DELIMITER) - 1#define CDATA_BEGIN "<![CDATA["#define CDATA_BEGIN_LEN sizeof(CDATA_BEGIN) - 1#define CDATA_END "]]>"#define CDATA_END_LEN sizeof(CDATA_END) - 1#define EQUALS "="#define EQUALS_LEN sizeof(EQUALS) - 1#define WHITESPACE " "#define WHITESPACE_LEN sizeof(WHITESPACE) - 1#define NEWLINE "\n"#define NEWLINE_LEN sizeof(NEWLINE) - 1#define MAX_VAL_BUF 144#define SCALAR_STR "SCALAR"#define SCALAR_STR_LEN sizeof(SCALAR_STR) - 1#define VECTOR_STR "VECTOR"#define VECTOR_STR_LEN sizeof(VECTOR_STR) - 1#define RESPONSE_STR "RESPONSE"#define RESPONSE_STR_LEN sizeof(RESPONSE_STR) - 1/*------------------------------ Begin xml_element Functions ------------------------------*//****f* xml_element/xml_elem_free_non_recurse * NAME * xml_elem_free_non_recurse * SYNOPSIS * void xml_elem_free_non_recurse(xml_element* root) * FUNCTION * free a single xml element. child elements will not be freed. * INPUTS * root - the element to free * RESULT * void * NOTES * SEE ALSO * xml_elem_free () * xml_elem_new () * SOURCE */void xml_elem_free_non_recurse(xml_element* root) { if(root) { xml_element_attr* attrs = Q_Head(&root->attrs); while(attrs) { my_free(attrs->key); my_free(attrs->val); my_free(attrs); attrs = Q_Next(&root->attrs); } Q_Destroy(&root->children); Q_Destroy(&root->attrs); if(root->name) { free((char *)root->name); root->name = NULL; } simplestring_free(&root->text); my_free(root); }}/******//****f* xml_element/xml_elem_free * NAME * xml_elem_free * SYNOPSIS * void xml_elem_free(xml_element* root) * FUNCTION * free an xml element and all of its child elements * INPUTS * root - the root of an xml tree you would like to free * RESULT * void * NOTES * SEE ALSO * xml_elem_free_non_recurse () * xml_elem_new () * SOURCE */void xml_elem_free(xml_element* root) { if(root) { xml_element* kids = Q_Head(&root->children); while(kids) { xml_elem_free(kids); kids = Q_Next(&root->children); } xml_elem_free_non_recurse(root); }}/******//****f* xml_element/xml_elem_new * NAME * xml_elem_new * SYNOPSIS * xml_element* xml_elem_new() * FUNCTION * allocates and initializes a new xml_element * INPUTS * none * RESULT * xml_element* or NULL. NULL indicates an out-of-memory condition. * NOTES * SEE ALSO * xml_elem_free () * xml_elem_free_non_recurse () * SOURCE */xml_element* xml_elem_new() { xml_element* elem = calloc(1, sizeof(xml_element)); if(elem) { Q_Init(&elem->children); Q_Init(&elem->attrs); simplestring_init(&elem->text); /* init empty string in case we don't find any char data */ simplestring_addn(&elem->text, "", 0); } return elem;}/******/static int xml_elem_writefunc(int (*fptr)(void *data, const char *text, int size), const char *text, void *data, int len){ return fptr && text ? fptr(data, text, len ? len : strlen(text)) : 0;}static int create_xml_escape(char *pString, unsigned char c){ int counter = 0; pString[counter++] = '&'; pString[counter++] = '#'; if(c >= 100) { pString[counter++] = c / 100 + '0'; c = c % 100; } pString[counter++] = c / 10 + '0'; c = c % 10; pString[counter++] = c + '0'; pString[counter++] = ';'; return counter; }#define non_ascii(c) (c > 127)#define non_print(c) (!isprint(c))#define markup(c) (c == '&' || c == '\"' || c == '>' || c == '<')#define entity_length(c) ( (c >= 100) ? 3 : ((c >= 10) ? 2 : 1) ) + 3; /* "&#" + c + ";" *//* * xml_elem_entity_escape * * Purpose: * escape reserved xml chars and non utf-8 chars as xml entities * Comments: * The return value may be a new string, or null if no * conversion was performed. In the latter case, *newlen will * be 0. * Flags (to escape) * xml_elem_no_escaping = 0x000, * xml_elem_entity_escaping = 0x002, // escape xml special chars as entities * xml_elem_non_ascii_escaping = 0x008, // escape chars above 127 * xml_elem_cdata_escaping = 0x010, // wrap in cdata */static char* xml_elem_entity_escape(const char* buf, int old_len, int *newlen, XML_ELEM_ESCAPING flags) { char *pRetval = 0; int iNewBufLen=0;#define should_escape(c, flag) ( ((flag & xml_elem_markup_escaping) && markup(c)) || \ ((flag & xml_elem_non_ascii_escaping) && non_ascii(c)) || \ ((flag & xml_elem_non_print_escaping) && non_print(c)) ) if(buf && *buf) { const unsigned char *bufcopy; char *NewBuffer; int ToBeXmlEscaped=0; int iLength; bufcopy = buf; iLength= old_len ? old_len : strlen(buf); while(*bufcopy) { if( should_escape(*bufcopy, flags) ) { /* the length will increase by length of xml escape - the character length */ iLength += entity_length(*bufcopy); ToBeXmlEscaped=1; } bufcopy++; } if(ToBeXmlEscaped) { NewBuffer= malloc(iLength+1); if(NewBuffer) { bufcopy=buf; while(*bufcopy) { if(should_escape(*bufcopy, flags)) { iNewBufLen += create_xml_escape(NewBuffer+iNewBufLen,*bufcopy); } else { NewBuffer[iNewBufLen++]=*bufcopy; } bufcopy++; } NewBuffer[iNewBufLen] = 0; pRetval = NewBuffer; } } } if(newlen) { *newlen = iNewBufLen; } return pRetval;}static void xml_element_serialize(xml_element *el, int (*fptr)(void *data, const char *text, int size), void *data, XML_ELEM_OUTPUT_OPTIONS options, int depth){ int i; static STRUCT_XML_ELEM_OUTPUT_OPTIONS default_opts = {xml_elem_pretty, xml_elem_markup_escaping | xml_elem_non_print_escaping, XML_DECL_ENCODING_DEFAULT}; static char whitespace[] = " " " " " "; depth++; if(!el) { fprintf(stderr, "Nothing to write\n"); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -