著者:後藤大地
今回は前回作ったサンプルコードをベースに、XMLデータをJSON(JavaScript Object Notation)形式に変換する例を紹介する。XMLデータをJSON形式に変換する、またはその逆を実施するのは需要の高い処理だ。今回紹介するのはサンプルレベルのコードだが、それなりに実用的なコードが書けることをわかってもらえるだろう。
記事本文掲載のシェルスクリプトマガジンvol.53は以下のリンク先でご購入できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <stdio.h> #include <expat.h> static void XMLCALL begin(void *, const XML_Char*, const XML_Char**); static void XMLCALL end(void *, const XML_Char *); static int depth = 0; int main(int argc, char *argv[]) { char buf[BUFSIZ]; int len, done; XML_Parser parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, begin, end); do { len = fread(buf, 1, sizeof(buf), stdin); done = len < sizeof(buf); if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) return 1; } while (!done); XML_ParserFree(parser); return 0; } static void XMLCALL begin(void *d, const XML_Char *name, const XML_Char **attr) { for (int i = 0; i < depth; i++) printf("→"); printf("%s\n", name); ++depth; } static void XMLCALL end(void *d, const XML_Char * name) { --depth; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="UTF-8"?> <document> <docgroup> <docinfo> <title><p>タイトル</p></title> <author><p>名前</p></author> <firstedition><p>編集開始日</p></firstedition> <lastmodified><p>編集終了日</p></lastmodified> </docinfo> <docgroup> <docinfo> <title><p>章タイトル</p></title> </docinfo> <p>説明1</p> <p>説明2</p> </docgroup> </docgroup> </document> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CC= cc RM= rm -f EXPAT= -lexpat LIBDIR= /usr/local/lib INCLUDEDIR= /usr/local/include CFLAGS= -I${INCLUDEDIR} -L${LIBDIR} ${EXPAT} SRC= xml2json.c OUT= xml2json build: ${CC} -o ${OUT} ${CFLAGS} ${SRC} clean: ${RM} ${OUT} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#include <stdio.h> #include <string.h> #include <expat.h> static void XMLCALL begin(void *, const XML_Char*, const XML_Char**); static void XMLCALL end(void *, const XML_Char *); static int depth = 0; static char *struct_elements[] = { "document", "docgroup", "docinfo" }; static char *key_elements[] = { "title", "author", "firstedition", "lastmodified" }; static char *value_elements[] = { "p", }; int main(int argc, char *argv[]) { char buf[BUFSIZ]; int len, done; XML_Parser parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, begin, end); do { len = fread(buf, 1, sizeof(buf), stdin); done = len < sizeof(buf); if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) return 1; } while (!done); XML_ParserFree(parser); return 0; } static void XMLCALL begin(void *d, const XML_Char *name, const XML_Char **attr) { int len, done; done = 0; len = sizeof(struct_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(struct_elements[i], name)) { printf("構造化要素: %s\n", name); done = 1; } } len = sizeof(key_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(key_elements[i], name)) { printf("鍵要素: %s\n", name); done = 1; } } len = sizeof(value_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(value_elements[i], name)) { printf("値要素: %s\n", name); done = 1; } } ++depth; } static void XMLCALL end(void *d, const XML_Char * name) { --depth; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
#include <stdio.h> #include <string.h> #include <expat.h> static void XMLCALL begin(void *, const XML_Char*, const XML_Char**); static void XMLCALL end(void *, const XML_Char *); static char *struct_elements[] = { "document", "docgroup", "docinfo" }; static char *key_elements[] = { "title", "author", "firstedition", "lastmodified" }; static char *value_elements[] = { "p", }; static int depth = 0; static char *pre_element; int main(int argc, char *argv[]) { char buf[BUFSIZ]; int len, done; XML_Parser parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, begin, end); do { len = fread(buf, 1, sizeof(buf), stdin); done = len < sizeof(buf); if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) return 1; } while (!done); XML_ParserFree(parser); return 0; } static void XMLCALL begin(void *d, const XML_Char *name, const XML_Char **attr) { int len, done; done = 0; len = sizeof(struct_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(struct_elements[i], name)) { if (0 == strcmp("document", name)) printf("{ "); for (int i = 0; i < depth; i++) printf("\t"); printf("\"%s\": {\n", name); done = 1; pre_element = struct_elements[i]; } } len = sizeof(key_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(key_elements[i], name)) { for (int i = 0; i < depth; i++) printf("\t"); printf("\"%s\":", name); done = 1; pre_element = key_elements[i]; } } int parent_is_key = 0; len = sizeof(value_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(value_elements[i], name)) { for (int j = 0, k = sizeof(key_elements) / sizeof(char*); j < k; j++) { if (key_elements[j] == pre_element) { parent_is_key = 1; } } if (parent_is_key) { printf("\"値\",\n"); } else { for (int i = 0; i < depth; i++) printf("\t"); printf("\"content\": \"値\",\n"); } done = 1; pre_element = value_elements[i]; } } if (!done) pre_element = NULL; ++depth; } static void XMLCALL end(void *d, const XML_Char * name) { int len, done; --depth; done = 0; len = sizeof(struct_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(struct_elements[i], name)) { if (0 == strcmp("document", name)) printf("}\n"); else { for (int i = 0; i < depth; i++) printf("\t"); printf("},\n"); } done = 1; } } len = sizeof(key_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(key_elements[i], name)) { done = 1; } } len = sizeof(value_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(value_elements[i], name)) { done = 1; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
#include <stdio.h> #include <string.h> #include <expat.h> static void XMLCALL begin(void *, const XML_Char*, const XML_Char**); static void XMLCALL end(void *, const XML_Char *); static void XMLCALL chardata(void *, const XML_Char *, int); static char *struct_elements[] = { "document", "docgroup", "docinfo" }; static char *key_elements[] = { "title", "author", "firstedition", "lastmodified" }; static char *value_elements[] = { "p", }; static int depth = 0; static char *pre_element; int main(int argc, char *argv[]) { char buf[BUFSIZ]; int len, done; XML_Parser parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, begin, end); XML_SetCharacterDataHandler(parser, chardata); do { len = fread(buf, 1, sizeof(buf), stdin); done = len < sizeof(buf); if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) return 1; } while (!done); XML_ParserFree(parser); return 0; } static void XMLCALL begin(void *d, const XML_Char *name, const XML_Char **attr) { int len, done; done = 0; len = sizeof(struct_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(struct_elements[i], name)) { if (0 == strcmp("document", name)) printf("{ "); for (int i = 0; i < depth; i++) printf("\t"); printf("\"%s\": {\n", name); done = 1; pre_element = struct_elements[i]; } } len = sizeof(key_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(key_elements[i], name)) { for (int i = 0; i < depth; i++) printf("\t"); printf("\"%s\":", name); done = 1; pre_element = key_elements[i]; } } int parent_is_key = 0; len = sizeof(value_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(value_elements[i], name)) { for (int j = 0, k = sizeof(key_elements) / sizeof(char*); j < k; j++) { if (key_elements[j] == pre_element) { parent_is_key = 1; } } if (parent_is_key) { printf("\""); } else { for (int i = 0; i < depth; i++) printf("\t"); printf("\"content\": \""); } done = 1; pre_element = value_elements[i]; } } if (!done) pre_element = NULL; ++depth; } static void XMLCALL end(void *d, const XML_Char * name) { int len, done; --depth; done = 0; len = sizeof(struct_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(struct_elements[i], name)) { if (0 == strcmp("document", name)) printf("}\n"); else { for (int i = 0; i < depth; i++) printf("\t"); printf("},\n"); } done = 1; } } len = sizeof(key_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(key_elements[i], name)) { done = 1; } } len = sizeof(value_elements) / sizeof(char*); for (int i = 0; !done && i < len; i++) { if (0 == strcmp(value_elements[i], name)) { printf("\",\n"); done = 1; } } } static void chardata(void *data, const XML_Char *cdata, int len) { char *p; p = (char *)cdata; for (int i = 0; i < len; i++) if ('\n' != *p) putchar(*p++); } |