📄 xml_element.c
字号:
} if(!options) { options = &default_opts; } /* print xml declaration if at root level */ if(depth == 1) { xml_elem_writefunc(fptr, XML_DECL_START, data, XML_DECL_START_LEN); xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN); xml_elem_writefunc(fptr, XML_DECL_VERSION, data, XML_DECL_VERSION_LEN); if(options->encoding && *options->encoding) { xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN); xml_elem_writefunc(fptr, XML_DECL_ENCODING_ATTR, data, XML_DECL_ENCODING_ATTR_LEN); xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN); xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN); xml_elem_writefunc(fptr, options->encoding, data, 0); xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN); } xml_elem_writefunc(fptr, XML_DECL_END, data, XML_DECL_END_LEN); if(options->verbosity != xml_elem_no_white_space) { xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN); } } if(options->verbosity == xml_elem_pretty && depth > 2) { xml_elem_writefunc(fptr, whitespace, data, depth - 2); } /* begin element */ xml_elem_writefunc(fptr,START_TOKEN_BEGIN, data, START_TOKEN_BEGIN_LEN); if(el->name) { xml_elem_writefunc(fptr, el->name, data, 0); /* write attrs, if any */ if(Q_Size(&el->attrs)) { xml_element_attr* iter = Q_Head(&el->attrs); while( iter ) { xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN); xml_elem_writefunc(fptr, iter->key, data, 0); xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN); xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN); xml_elem_writefunc(fptr, iter->val, data, 0); xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN); iter = Q_Next(&el->attrs); } } } else { xml_elem_writefunc(fptr, "None", data, 0); } /* if no text and no children, use abbreviated form, eg: <foo/> */ if(!el->text.len && !Q_Size(&el->children)) { xml_elem_writefunc(fptr, EMPTY_START_TOKEN_END, data, EMPTY_START_TOKEN_END_LEN); } /* otherwise, print element contents */ else { xml_elem_writefunc(fptr, START_TOKEN_END, data, START_TOKEN_END_LEN); /* print text, if any */ if(el->text.len) { char* escaped_str = el->text.str; int buflen = el->text.len; if(options->escaping && options->escaping != xml_elem_cdata_escaping) { escaped_str = xml_elem_entity_escape(el->text.str, buflen, &buflen, options->escaping ); if(!escaped_str) { escaped_str = el->text.str; } } if(options->escaping & xml_elem_cdata_escaping) { xml_elem_writefunc(fptr, CDATA_BEGIN, data, CDATA_BEGIN_LEN); } xml_elem_writefunc(fptr, escaped_str, data, buflen); if(escaped_str != el->text.str) { my_free(escaped_str); } if(options->escaping & xml_elem_cdata_escaping) { xml_elem_writefunc(fptr, CDATA_END, data, CDATA_END_LEN); } } /* no text, so print child elems */ else { xml_element *kids = Q_Head(&el->children); i = 0; while( kids ) { if(i++ == 0) { if(options->verbosity != xml_elem_no_white_space) { xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN); } } xml_element_serialize(kids, fptr, data, options, depth); kids = Q_Next(&el->children); } if(i) { if(options->verbosity == xml_elem_pretty && depth > 2) { xml_elem_writefunc(fptr, whitespace, data, depth - 2); } } } xml_elem_writefunc(fptr, END_TOKEN_BEGIN, data, END_TOKEN_BEGIN_LEN); xml_elem_writefunc(fptr,el->name ? el->name : "None", data, 0); xml_elem_writefunc(fptr, END_TOKEN_END, data, END_TOKEN_END_LEN); } if(options->verbosity != xml_elem_no_white_space) { xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN); }}/* print buf to file */static int file_out_fptr(void *f, const char *text, int size){ fputs(text, (FILE *)f); return 0;}/* print buf to simplestring */static int simplestring_out_fptr(void *f, const char *text, int size){ simplestring* buf = (simplestring*)f; if(buf) { simplestring_addn(buf, text, size); } return 0;}/****f* xml_element/xml_elem_serialize_to_string * NAME * xml_elem_serialize_to_string * SYNOPSIS * void xml_element_serialize_to_string(xml_element *el, XML_ELEM_OUTPUT_OPTIONS options, int *buf_len) * FUNCTION * writes element tree as XML into a newly allocated buffer * INPUTS * el - root element of tree * options - options determining how output is written. see XML_ELEM_OUTPUT_OPTIONS * buf_len - length of returned buffer, if not null. * RESULT * char* or NULL. Must be free'd by caller. * NOTES * SEE ALSO * xml_elem_serialize_to_stream () * xml_elem_parse_buf () * SOURCE */char* xml_elem_serialize_to_string(xml_element *el, XML_ELEM_OUTPUT_OPTIONS options, int *buf_len){ simplestring buf; simplestring_init(&buf); xml_element_serialize(el, simplestring_out_fptr, (void *)&buf, options, 0); if(buf_len) { *buf_len = buf.len; } return buf.str;}/******//****f* xml_element/xml_elem_serialize_to_stream * NAME * xml_elem_serialize_to_stream * SYNOPSIS * void xml_elem_serialize_to_stream(xml_element *el, FILE *output, XML_ELEM_OUTPUT_OPTIONS options) * FUNCTION * writes element tree as XML into a stream (typically an opened file) * INPUTS * el - root element of tree * output - stream handle * options - options determining how output is written. see XML_ELEM_OUTPUT_OPTIONS * RESULT * void * NOTES * SEE ALSO * xml_elem_serialize_to_string () * xml_elem_parse_buf () * SOURCE */void xml_elem_serialize_to_stream(xml_element *el, FILE *output, XML_ELEM_OUTPUT_OPTIONS options){ xml_element_serialize(el, file_out_fptr, (void *)output, options, 0);}/******//*--------------------------** End xml_element Functions **--------------------------*//*----------------------* Begin Expat Handlers **---------------------*/typedef struct _xml_elem_data { xml_element* root; xml_element* current; XML_ELEM_INPUT_OPTIONS input_options; int needs_enc_conversion;} xml_elem_data;/* expat start of element handler */static void _xmlrpc_startElement(void *userData, const char *name, const char **attrs){ xml_element *c; xml_elem_data* mydata = (xml_elem_data*)userData; const char** p = attrs; if(mydata) { c = mydata->current; mydata->current = xml_elem_new(); mydata->current->name = (char*)strdup(name); mydata->current->parent = c; /* init attrs */ while(p && *p) { xml_element_attr* attr = malloc(sizeof(xml_element_attr)); if(attr) { attr->key = strdup(*p); attr->val = strdup(*(p+1)); Q_PushTail(&mydata->current->attrs, attr); p += 2; } } }}/* expat end of element handler */static void _xmlrpc_endElement(void *userData, const char *name){ xml_elem_data* mydata = (xml_elem_data*)userData; if(mydata && mydata->current && mydata->current->parent) { Q_PushTail(&mydata->current->parent->children, mydata->current); mydata->current = mydata->current->parent; }}/* expat char data handler */static void _xmlrpc_charHandler(void *userData, const char *s, int len){ xml_elem_data* mydata = (xml_elem_data*)userData; if(mydata && mydata->current) { /* Check if we need to decode utf-8 parser output to another encoding */ if(mydata->needs_enc_conversion && mydata->input_options->encoding) { int new_len = 0; char* add_text = utf8_decode(s, len, &new_len, mydata->input_options->encoding); if(add_text) { len = new_len; simplestring_addn(&mydata->current->text, add_text, len); free(add_text); return; } } simplestring_addn(&mydata->current->text, s, len); }}/******//*-------------------** End Expat Handlers **-------------------*//*-------------------** xml_elem_parse_buf **-------------------*//****f* xml_element/xml_elem_parse_buf * NAME * xml_elem_parse_buf * SYNOPSIS * xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTIONS options, XML_ELEM_ERROR error) * FUNCTION * parse a buffer containing XML into an xml_element in-memory tree * INPUTS * in_buf - buffer containing XML document * len - length of buffer * options - input options. optional * error - error result data. optional. check if result is null. * RESULT * void * NOTES * The returned data must be free'd by caller * SEE ALSO * xml_elem_serialize_to_string () * xml_elem_free () * SOURCE */xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTIONS options, XML_ELEM_ERROR error){ xml_element* xReturn = NULL; char buf[100] = ""; static STRUCT_XML_ELEM_INPUT_OPTIONS default_opts = {encoding_utf_8}; if(!options) { options = &default_opts; } if(in_buf) { XML_Parser parser; xml_elem_data mydata = {0}; parser = XML_ParserCreate(NULL); mydata.root = xml_elem_new(); mydata.current = mydata.root; mydata.input_options = options; mydata.needs_enc_conversion = options->encoding && strcmp(options->encoding, encoding_utf_8); XML_SetElementHandler(parser, (XML_StartElementHandler)_xmlrpc_startElement, (XML_EndElementHandler)_xmlrpc_endElement); XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler)_xmlrpc_charHandler); /* pass the xml_elem_data struct along */ XML_SetUserData(parser, (void*)&mydata); if(!len) { len = strlen(in_buf); } /* parse the XML */ if(XML_Parse(parser, in_buf, len, 1) == 0) { enum XML_Error err_code = XML_GetErrorCode(parser); int line_num = XML_GetCurrentLineNumber(parser); int col_num = XML_GetCurrentColumnNumber(parser); long byte_idx = XML_GetCurrentByteIndex(parser); int byte_total = XML_GetCurrentByteCount(parser); const char * error_str = XML_ErrorString(err_code); if(byte_idx >= 0) { snprintf(buf, sizeof(buf), "\n\tdata beginning %ld before byte index: %s\n", byte_idx > 10 ? 10 : byte_idx, in_buf + (byte_idx > 10 ? byte_idx - 10 : byte_idx)); } fprintf(stderr, "expat reports error code %i\n" "\tdescription: %s\n" "\tline: %i\n" "\tcolumn: %i\n" "\tbyte index: %ld\n" "\ttotal bytes: %i\n%s ", err_code, error_str, line_num, col_num, byte_idx, byte_total, buf); /* error condition */ if(error) { error->parser_code = (long)err_code; error->line = line_num; error->column = col_num; error->byte_index = byte_idx; error->parser_error = error_str; } } else { xReturn = (xml_element*)Q_Head(&mydata.root->children); xReturn->parent = NULL; } XML_ParserFree(parser); xml_elem_free_non_recurse(mydata.root); } return xReturn;}/******/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -