Home | History | Annotate | Download | only in examples
      1 /**
      2  * section: InputOutput
      3  * synopsis: Example of custom Input/Output
      4  * purpose: Demonstrate the use of xmlRegisterInputCallbacks
      5  *          to build a custom I/O layer, this is used in an
      6  *          XInclude method context to show how dynamic document can
      7  *          be built in a clean way.
      8  * usage: io1
      9  * test: io1 > io1.tmp && diff io1.tmp $(srcdir)/io1.res
     10  * author: Daniel Veillard
     11  * copy: see Copyright for the status of this software.
     12  */
     13 
     14 #include <stdio.h>
     15 #include <string.h>
     16 #include <libxml/parser.h>
     17 #include <libxml/tree.h>
     18 #include <libxml/xinclude.h>
     19 #include <libxml/xmlIO.h>
     20 
     21 #ifdef LIBXML_XINCLUDE_ENABLED
     22 static const char *result = "<list><people>a</people><people>b</people></list>";
     23 static const char *cur = NULL;
     24 static int rlen;
     25 
     26 /**
     27  * sqlMatch:
     28  * @URI: an URI to test
     29  *
     30  * Check for an sql: query
     31  *
     32  * Returns 1 if yes and 0 if another Input module should be used
     33  */
     34 static int
     35 sqlMatch(const char * URI) {
     36     if ((URI != NULL) && (!strncmp(URI, "sql:", 4)))
     37         return(1);
     38     return(0);
     39 }
     40 
     41 /**
     42  * sqlOpen:
     43  * @URI: an URI to test
     44  *
     45  * Return a pointer to the sql: query handler, in this example simply
     46  * the current pointer...
     47  *
     48  * Returns an Input context or NULL in case or error
     49  */
     50 static void *
     51 sqlOpen(const char * URI) {
     52     if ((URI == NULL) || (strncmp(URI, "sql:", 4)))
     53         return(NULL);
     54     cur = result;
     55     rlen = strlen(result);
     56     return((void *) cur);
     57 }
     58 
     59 /**
     60  * sqlClose:
     61  * @context: the read context
     62  *
     63  * Close the sql: query handler
     64  *
     65  * Returns 0 or -1 in case of error
     66  */
     67 static int
     68 sqlClose(void * context) {
     69     if (context == NULL) return(-1);
     70     cur = NULL;
     71     rlen = 0;
     72     return(0);
     73 }
     74 
     75 /**
     76  * sqlRead:
     77  * @context: the read context
     78  * @buffer: where to store data
     79  * @len: number of bytes to read
     80  *
     81  * Implement an sql: query read.
     82  *
     83  * Returns the number of bytes read or -1 in case of error
     84  */
     85 static int
     86 sqlRead(void * context, char * buffer, int len) {
     87    const char *ptr = (const char *) context;
     88 
     89    if ((context == NULL) || (buffer == NULL) || (len < 0))
     90        return(-1);
     91 
     92    if (len > rlen) len = rlen;
     93    memcpy(buffer, ptr, len);
     94    rlen -= len;
     95    return(len);
     96 }
     97 
     98 const char *include = "<?xml version='1.0'?>\n\
     99 <document xmlns:xi=\"http://www.w3.org/2003/XInclude\">\n\
    100   <p>List of people:</p>\n\
    101   <xi:include href=\"sql:select_name_from_people\"/>\n\
    102 </document>\n";
    103 
    104 int main(void) {
    105     xmlDocPtr doc;
    106 
    107     /*
    108      * this initialize the library and check potential ABI mismatches
    109      * between the version it was compiled for and the actual shared
    110      * library used.
    111      */
    112     LIBXML_TEST_VERSION
    113 
    114     /*
    115      * register the new I/O handlers
    116      */
    117     if (xmlRegisterInputCallbacks(sqlMatch, sqlOpen, sqlRead, sqlClose) < 0) {
    118         fprintf(stderr, "failed to register SQL handler\n");
    119 	exit(1);
    120     }
    121     /*
    122      * parse include into a document
    123      */
    124     doc = xmlReadMemory(include, strlen(include), "include.xml", NULL, 0);
    125     if (doc == NULL) {
    126         fprintf(stderr, "failed to parse the including file\n");
    127 	exit(1);
    128     }
    129 
    130     /*
    131      * apply the XInclude process, this should trigger the I/O just
    132      * registered.
    133      */
    134     if (xmlXIncludeProcess(doc) <= 0) {
    135         fprintf(stderr, "XInclude processing failed\n");
    136 	exit(1);
    137     }
    138 
    139 #ifdef LIBXML_OUTPUT_ENABLED
    140     /*
    141      * save the output for checking to stdout
    142      */
    143     xmlDocDump(stdout, doc);
    144 #endif
    145 
    146     /*
    147      * Free the document
    148      */
    149     xmlFreeDoc(doc);
    150 
    151     /*
    152      * Cleanup function for the XML library.
    153      */
    154     xmlCleanupParser();
    155     /*
    156      * this is to debug memory for regression tests
    157      */
    158     xmlMemoryDump();
    159     return(0);
    160 }
    161 #else
    162 int main(void) {
    163     fprintf(stderr, "XInclude support not compiled in\n");
    164     exit(1);
    165 }
    166 #endif
    167