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 io1.res ; rm -f io1.tmp
|
---|
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
|
---|