myio_xml.c
最終更新:2009/12/19
001: /* myio_xml.h
002: * libxml2 / libxslt のサンプルコード
003: */
004:
005: #include <stdio.h>
006: #include <string.h>
007: #include "myio_xml.h"
008:
009: #if defined(WIN32) || defined(WINDOWS) || defined(MSVC)
010: #define snprintf sprintf_s
011: #define strdup _strdup
012: #endif
013:
014: #ifdef LIBXML_PUSH_ENABLED
015:
016: /*
017: * XML ドキュメントの読み込み
018: */
019: xmlDocPtr my_xml_read (
020: MYIO *in
021: ) {
022: xmlDocPtr doc = NULL;
023: xmlParserCtxtPtr ctxt = NULL;
024:
025: char buf[1024];
026: int nbytes = 0;
027:
028: //if(1)puts("(1)");
029:
030: if (!in) {
031: return NULL;
032: }
033:
034: //if(1)puts("(2)");
035:
036: nbytes = MYIO_read(in, buf, sizeof(buf));
037: if (nbytes <= 0) {
038: return NULL;
039: }
040:
041: //if(1)puts("(3)");
042:
043: ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, nbytes, "dummy.xml");
044: if (ctxt == NULL) {
045: return NULL;
046: }
047:
048: //if(1)puts("(4)");
049:
050: while((nbytes = MYIO_read(in, buf, sizeof(buf))) > 0) {
051: //if(1)printf("(4.1) nbytes=[%d]\n", nbytes);
052: xmlParseChunk(ctxt, buf, nbytes, 0);
053: }
054:
055: //if(1)printf("(5) nbytes=[%d]\n", nbytes);
056:
057: //// if (!nbytes) {
058:
059: //if(1)puts("(5.1)");
060:
061: xmlParseChunk(ctxt, buf, 0, 1);
062:
063: if (ctxt->wellFormed) {
064:
065: //if(1)puts("(5.2)");
066:
067: doc = ctxt->myDoc;
068: }
069: //// }
070:
071: //if(1)puts("(6)");
072:
073: xmlFreeParserCtxt(ctxt);
074:
075: return doc;
076: }
077:
078: #else /* ! LIBXML_PUSH_ENABLED */
079:
080: xmlDocPtr my_xml_read (
081: MYIO *in
082: ) {
083: return NULL;
084: }
085:
086: #endif /* LIBXML_PUSH_ENABLED */
087:
088: #if defined(LIBXML_TREE_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
089:
090: /*
091: * XML ドキュメントの書き込み
092: */
093: int my_xml_write (
094: MYIO *out
095: , xmlDocPtr doc
096: , const char * enc
097: ) {
098: xmlChar *xml_buff = NULL;
099: int buffer_size = 0;
100: int write_size = 0;
101:
102: if (!out || !doc) {
103: return -1;
104: }
105:
106: if (!enc) {
107: xmlDocDumpFormatMemoryEnc(doc, &xml_buff, &buffer_size, enc, 1);
108: } else {
109: xmlDocDumpFormatMemory(doc, &xml_buff, &buffer_size, 1);
110: }
111: //write_size = MYIO_write(out, xml_buf, buffer_size);
112: {
113: int o = 0;
114: int nbytes = 0;
115: while (o<buffer_size) {
116: nbytes = out->method->write(out, (const char*)(xml_buff+o), buffer_size-o);
117: if (nbytes <= 0) {
118: break;
119: }
120: o += nbytes;
121: }
122: write_size = o;
123: if (nbytes < 0) {
124: write_size = -1;
125: }
126: }
127: xmlFree(xml_buff);
128:
129: return write_size;
130: }
131:
132: #else /* ! LIBXML_TREE_ENABLED || ! LIBXML_OUTPUT_ENABLED */
133:
134: int my_xml_write (
135: MYIO *out
136: , xmlDocPtr doc
137: , const char * enc
138: ) return -1;
139: }
140:
141: #endif /* LIBXML_TREE_ENABLED && LIBXML_OUTPUT_ENABLED */
142:
143: /*
144: * サンプル:属性の表示
145: */
146: void print_xmlAttrs(MYIO *out, xmlAttrPtr attrs) {
147: xmlAttrPtr p = attrs;
148: if (!out || !p) {
149: return;
150: }
151: for (; p; p=p->next) {
152: if (p->ns) {
153: MYIO_puts(out, " (");
154: MYIO_puts(out, (const char*)(p->ns->href));
155: MYIO_puts(out, "):");
156: MYIO_puts(out, (const char*)(p->name));
157: MYIO_puts(out, "=\"");
158: MYIO_puts(out, (const char*)(p->children->content));
159: MYIO_puts(out, "\"");
160: } else {
161: MYIO_puts(out, " ");
162: MYIO_puts(out, (const char*)(p->name));
163: MYIO_puts(out, "=\"");
164: MYIO_puts(out, (const char*)(p->children->content));
165: MYIO_puts(out, "\"");
166: }
167: }
168: }
169:
170: /*
171: * サンプル:ノードセットの表示
172: */
173: void print_xpath_nodes(MYIO *out, xmlNodeSetPtr nodes) {
174: xmlNodePtr cur = NULL;
175: int size = 0;
176: int i = 0;
177:
178: if (!out || !nodes)
179: return;
180:
181: size = nodes->nodeNr;
182:
183: for(i = 0; i < size; ++i) {
184: if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
185: cur = nodes->nodeTab[i];
186: if(cur->ns) {
187: MYIO_puts(out, "<(");
188: MYIO_puts(out, (const char*)(cur->ns->href));
189: MYIO_puts(out, "):");
190: MYIO_puts(out, (const char*)(cur->name));
191: if (cur->properties) {
192: print_xmlAttrs(out, cur->properties);
193: }
194: MYIO_puts(out, "/>");
195: } else {
196: MYIO_puts(out, "<");
197: MYIO_puts(out, (const char*)(cur->name));
198: if (cur->properties) {
199: print_xmlAttrs(out, cur->properties);
200: }
201: MYIO_puts(out, "/>");
202: }
203: } else {
204: cur = nodes->nodeTab[i];
205: switch (cur->type) {
206: case 3:
207: if (cur->content) {
208: MYIO_puts(out, (const char*)(cur->content));
209: }
210: break;
211: case 2:
212: if (cur->children && cur->children->content) {
213: MYIO_puts(out, (const char*)(cur->children->content));
214: }
215: default:
216: ;/* ignore. */
217: }
218: }
219: MYIO_puts(out, "\n");
220: }
221: }
222: /*
223: * サンプル:XPath 検索結果の表示(my_xml_xpath_do 用コールバック関数)
224: * void func(void *func_ctx, xmlXPathObjectPtr xpathObj);
225: */
226: void print_xpath_cb (MYIO *out, xmlXPathObjectPtr xpathObj) {
227: if (!out || !xpathObj)
228: return;
229:
230: switch (xpathObj->type) {
231: case XPATH_NODESET:
232: print_xpath_nodes(out, xpathObj->nodesetval);
233: break;
234: case XPATH_NUMBER:
235: {
236: char buf[16];
237: snprintf(buf, 16, "%f", xpathObj->floatval);
238: MYIO_puts(out, buf);
239: }
240: break;
241: case XPATH_BOOLEAN:
242: MYIO_puts(out, (xpathObj->boolval)?"true":"false");
243: break;
244: case XPATH_STRING:
245: MYIO_puts(out, (const char*)(xpathObj->stringval));
246: break;
247: default:
248: ; /* ignore. */
249: }
250: MYIO_puts(out, "\n");
251: }
252:
253: /* XPath 検索
254: * 返り値:
255: * 1: 成功
256: * 0: 失敗
257: */
258:
259: int my_xml_search_do(
260: xmlDocPtr doc /* XMLドキュメント */
261: , const char *expr /* XPath の式 */
262: , void *func /* 検索結果を処理するコールバック関数 */
263: , void *func_ctx /* コールバック関数で使用するコンテクストデータ */
264: , const char **ns_array
265: , int ns_size
266: ) {
267:
268: int error_flag = 0;
269:
270: xmlXPathContextPtr xpathCtx = NULL;
271: xmlXPathObjectPtr xpathObj = NULL;
272:
273: if (!doc || !expr) {
274: return 0;
275: }
276:
277: xpathCtx = xmlXPathNewContext(doc);
278: if(! xpathCtx) {
279: error_flag = 1;
280: goto _FINALLY_;
281: }
282:
283: if (ns_size>0 && ns_array) {
284: char *prefix = NULL;
285: char *href = NULL;
286: int i=0;
287: for (; i<ns_size; i++) {
288: prefix = strdup(ns_array[i]);
289: href = strchr(prefix, '=');
290: if (href) {
291: *(href++) = '\0';
292: xmlXPathRegisterNs(xpathCtx, (const xmlChar*)prefix, (const xmlChar*)href);
293: }
294: free(prefix);
295: }
296: }
297:
298: xpathObj = xmlXPathEvalExpression((const xmlChar*)expr, xpathCtx);
299: if(! xpathObj) {
300: error_flag = 1;
301: goto _FINALLY_;
302: }
303:
304: if (func) {
305: void (*f)(void *func_ctx, xmlXPathObjectPtr) = func;
306: f(func_ctx, xpathObj);
307: }
308:
309: _FINALLY_:
310:
311: if (xpathObj) {
312: xmlXPathFreeObject(xpathObj);
313: xpathObj = NULL;
314: }
315:
316: if (xpathCtx) {
317: xmlXPathFreeContext(xpathCtx);
318: xpathCtx = NULL;
319: }
320:
321: if (error_flag) {
322: return 0;
323: }
324:
325: return 1;
326: }
327: /*
328: * 返り値:
329: * XSLT 変換結果
330: * 失敗時は NULL
331: */
332:
333: xmlDocPtr my_xml_transform (
334: xmlDocPtr doc
335: , xsltStylesheetPtr style
336: ) {
337: int error_flag = 0;
338:
339: xmlDocPtr res = NULL;
340: const char **params=NULL;
341:
342: if (!doc || !style) {
343: return NULL;
344: }
345:
346: res = xsltApplyStylesheet(style, doc, params);
347: if (!res) {
348: error_flag = 1;
349: goto _FINALLY_;
350: }
351:
352: _FINALLY_:
353:
354:
355: if (error_flag) {
356: return 0;
357: }
358:
359: return res;
360: }
361:
362: int MYIO_xslt_write(
363: MYIO *out
364: , xmlDocPtr res
365: , xsltStylesheetPtr style
366: ) {
367: char *buf = NULL;
368: int buf_size = 0;
369:
370: int write_size=0;
371:
372: if (!out || !res) {
373: return -1;
374: }
375:
376: if (xsltSaveResultToString((xmlChar**)&buf, &buf_size, res, style)<0) {
377: return -1;
378: }
379:
380: if (buf && buf_size>0) {
381: int o = 0;
382: int nbytes = 0;
383: while (o<buf_size) {
384: nbytes = MYIO_write(out, buf+o, buf_size-o);
385: if (nbytes <= 0) {
386: break;
387: }
388: o += nbytes;
389: }
390: write_size = o;
391: if (nbytes < 0) {
392: write_size = -1;
393: }
394: }
395:
396: if (buf) {
397: xmlFree(buf); /* free ではなく、xmlFree を使う */
398: buf = NULL;
399: }
400:
401: return write_size;
402: }
403:
404: int my_xslt_save (
405: const char *out_filename
406: , xmlDocPtr res
407: , xsltStylesheetPtr style
408: ) {
409: if (!out_filename || !res || !style) {
410: return -1;
411: }
412:
413: return xsltSaveResultToFilename(out_filename, res, style, 0);
414: }
415:
416: void my_xml_init () {
417: xmlInitParser();
418: }
419:
420: void my_xml_clear() {
421: xmlCleanupParser();
422: xmlMemoryDump();
423: }
![]() | KAKU PROJECT (2009) |