myio_xml.c

最終更新:2009/12/19

myio_xml.c

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: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)