Return to xmlstream.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / docs / examples |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. ! 9: * ! 10: * This software is licensed as described in the file COPYING, which ! 11: * you should have received as part of this distribution. The terms ! 12: * are also available at https://curl.haxx.se/docs/copyright.html. ! 13: * ! 14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell ! 15: * copies of the Software, and permit persons to whom the Software is ! 16: * furnished to do so, under the terms of the COPYING file. ! 17: * ! 18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ! 19: * KIND, either express or implied. ! 20: * ! 21: ***************************************************************************/ ! 22: /* <DESC> ! 23: * Stream-parse a document using the streaming Expat parser. ! 24: * </DESC> ! 25: */ ! 26: /* Written by David Strauss ! 27: * ! 28: * Expat => https://libexpat.github.io/ ! 29: * ! 30: * gcc -Wall -I/usr/local/include xmlstream.c -lcurl -lexpat -o xmlstream ! 31: * ! 32: */ ! 33: ! 34: #include <stdio.h> ! 35: #include <stdlib.h> ! 36: #include <string.h> ! 37: #include <assert.h> ! 38: ! 39: #include <expat.h> ! 40: #include <curl/curl.h> ! 41: ! 42: struct MemoryStruct { ! 43: char *memory; ! 44: size_t size; ! 45: }; ! 46: ! 47: struct ParserStruct { ! 48: int ok; ! 49: size_t tags; ! 50: size_t depth; ! 51: struct MemoryStruct characters; ! 52: }; ! 53: ! 54: static void startElement(void *userData, const XML_Char *name, ! 55: const XML_Char **atts) ! 56: { ! 57: struct ParserStruct *state = (struct ParserStruct *) userData; ! 58: state->tags++; ! 59: state->depth++; ! 60: ! 61: /* Get a clean slate for reading in character data. */ ! 62: free(state->characters.memory); ! 63: state->characters.memory = NULL; ! 64: state->characters.size = 0; ! 65: } ! 66: ! 67: static void characterDataHandler(void *userData, const XML_Char *s, int len) ! 68: { ! 69: struct ParserStruct *state = (struct ParserStruct *) userData; ! 70: struct MemoryStruct *mem = &state->characters; ! 71: ! 72: char *ptr = realloc(mem->memory, mem->size + len + 1); ! 73: if(!ptr) { ! 74: /* Out of memory. */ ! 75: fprintf(stderr, "Not enough memory (realloc returned NULL).\n"); ! 76: state->ok = 0; ! 77: return; ! 78: } ! 79: ! 80: mem->memory = ptr; ! 81: memcpy(&(mem->memory[mem->size]), s, len); ! 82: mem->size += len; ! 83: mem->memory[mem->size] = 0; ! 84: } ! 85: ! 86: static void endElement(void *userData, const XML_Char *name) ! 87: { ! 88: struct ParserStruct *state = (struct ParserStruct *) userData; ! 89: state->depth--; ! 90: ! 91: printf("%5lu %10lu %s\n", state->depth, state->characters.size, name); ! 92: } ! 93: ! 94: static size_t parseStreamCallback(void *contents, size_t length, size_t nmemb, ! 95: void *userp) ! 96: { ! 97: XML_Parser parser = (XML_Parser) userp; ! 98: size_t real_size = length * nmemb; ! 99: struct ParserStruct *state = (struct ParserStruct *) XML_GetUserData(parser); ! 100: ! 101: /* Only parse if we're not already in a failure state. */ ! 102: if(state->ok && XML_Parse(parser, contents, real_size, 0) == 0) { ! 103: int error_code = XML_GetErrorCode(parser); ! 104: fprintf(stderr, "Parsing response buffer of length %lu failed" ! 105: " with error code %d (%s).\n", ! 106: real_size, error_code, XML_ErrorString(error_code)); ! 107: state->ok = 0; ! 108: } ! 109: ! 110: return real_size; ! 111: } ! 112: ! 113: int main(void) ! 114: { ! 115: CURL *curl_handle; ! 116: CURLcode res; ! 117: XML_Parser parser; ! 118: struct ParserStruct state; ! 119: ! 120: /* Initialize the state structure for parsing. */ ! 121: memset(&state, 0, sizeof(struct ParserStruct)); ! 122: state.ok = 1; ! 123: ! 124: /* Initialize a namespace-aware parser. */ ! 125: parser = XML_ParserCreateNS(NULL, '\0'); ! 126: XML_SetUserData(parser, &state); ! 127: XML_SetElementHandler(parser, startElement, endElement); ! 128: XML_SetCharacterDataHandler(parser, characterDataHandler); ! 129: ! 130: /* Initialize a libcurl handle. */ ! 131: curl_global_init(CURL_GLOBAL_DEFAULT); ! 132: curl_handle = curl_easy_init(); ! 133: curl_easy_setopt(curl_handle, CURLOPT_URL, ! 134: "https://www.w3schools.com/xml/simple.xml"); ! 135: curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, parseStreamCallback); ! 136: curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)parser); ! 137: ! 138: printf("Depth Characters Closing Tag\n"); ! 139: ! 140: /* Perform the request and any follow-up parsing. */ ! 141: res = curl_easy_perform(curl_handle); ! 142: if(res != CURLE_OK) { ! 143: fprintf(stderr, "curl_easy_perform() failed: %s\n", ! 144: curl_easy_strerror(res)); ! 145: } ! 146: else if(state.ok) { ! 147: /* Expat requires one final call to finalize parsing. */ ! 148: if(XML_Parse(parser, NULL, 0, 1) == 0) { ! 149: int error_code = XML_GetErrorCode(parser); ! 150: fprintf(stderr, "Finalizing parsing failed with error code %d (%s).\n", ! 151: error_code, XML_ErrorString(error_code)); ! 152: } ! 153: else { ! 154: printf(" --------------\n"); ! 155: printf(" %lu tags total\n", state.tags); ! 156: } ! 157: } ! 158: ! 159: /* Clean up. */ ! 160: free(state.characters.memory); ! 161: XML_ParserFree(parser); ! 162: curl_easy_cleanup(curl_handle); ! 163: curl_global_cleanup(); ! 164: ! 165: return 0; ! 166: }