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) |