diff options
| author | ryo <ryo@repack.top> | 2026-03-09 18:48:24 +0000 |
|---|---|---|
| committer | ryo <ryo@repack.top> | 2026-03-09 18:48:24 +0000 |
| commit | 01bd6113aa1a6d58a8d7d003b9ffdc49720951f3 (patch) | |
| tree | 85c5f07ed071889eab17f14acbaee43bafc23519 | |
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | main.c | 140 | ||||
| -rw-r--r-- | test.xml | 24 |
3 files changed, 166 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..24314bf --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +demo: main.c + tcc -o $@ -I/usr/include/libxml2 -lxml2 $< @@ -0,0 +1,140 @@ +/* + * XML to SQL converter + * Author: ryo@repack.top + * Website: https://repack.top/~ryo + * Version: alpha + */ + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define astrtr(s) s[strlen(s)-1] = '\0' +#define astrcmp(s1, s2) xmlStrcmp(s1, (xmlChar *)s2) == 0 +#define asprintf(dst, ...) sprintf(dst+strlen(dst), __VA_ARGS__) + +void query_create(xmlNode *root, char query[]); +void query_insert(xmlNode *root, char query[]); + +int main(int argc, char *argv[]) +{ + xmlDocPtr doc; + xmlNodePtr root; + char *query = malloc(2048 * sizeof(char)); + + if (argc < 2) { + fprintf(stderr, "no file specified\n"); + return 1; + } + + doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS); + if (doc == NULL) { + fprintf(stderr, "can not parse the document\n"); + return 1; + } + + root = xmlDocGetRootElement(doc); + + query_create(root, query); + query_insert(root, query); + puts(query); + + xmlFreeDoc(doc); + free(query); + return 0; +} + +void query_create(xmlNode *root, char *query) +{ + xmlNode *cur, *parent; + int uuid = 0, end, nested = 0; + + cur = root; + while (cur) { + asprintf(query, "CREATE TABLE %s(", cur->name); + cur = cur->children; + if (cur->children->type == XML_ELEMENT_NODE) { + parent = cur->parent; + nested = 1; + cur = cur->children; + } + + while (cur->children->type == XML_TEXT_NODE) { + if (astrcmp(cur->name, "uuid")) + uuid = 1; + + asprintf(query, "%s,", cur->name); + + cur = cur->next; + if (cur == NULL) break; + } + if (nested) { + cur = parent->next; + nested = 0; + } + + if (!uuid) { + asprintf(query, "%s_uuid,", root->name); + } + + astrtr(query); + strcat(query, ");\n"); + } +} + +void query_insert(xmlNode *root, char *query) +{ + xmlNode *cur, *parent; + int uuid = 0, end, nested = 0; + + cur = root; + while (cur) { + asprintf(query, "INSERT INTO %s VALUES(", cur->name); + cur = cur->children; + if (cur->children->type == XML_ELEMENT_NODE) { + parent = cur->parent; + nested = 1; + cur = cur->children; + } + + while (cur->children->type == XML_TEXT_NODE) { + if (astrcmp(cur->name, "uuid")) + uuid = 1; + + asprintf(query, "'%s',", xmlNodeGetContent(cur)); + + if (cur->next == NULL) { + if (nested) { + if (cur->parent == parent->last) { + break; + } + else { + astrtr(query); + strcat(query, "),\n("); + cur = cur->parent->next->children; + } + } else { + cur = cur->next; + break; + } + } else + cur = cur->next; + } + + if (nested) { + cur = parent->next; + nested = 0; + } + + if (!uuid) { + asprintf(query, "'%s',", xmlNodeGetContent(root->children)); + } + + astrtr(query); + strcat(query, ");\n"); + } + astrtr(query); +} + diff --git a/test.xml b/test.xml new file mode 100644 index 0000000..4a06a53 --- /dev/null +++ b/test.xml @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<library> + <uuid>550e8400-e29b-41d4-a716-446655440000</uuid> + <title>Main Library</title> + <books> + <book> + <id>1</id> + <title>The Great Gatsby</title> + <author>F. Scott Fitzgerald</author> + <publication_year>1925</publication_year> + </book> + <book> + <id>2</id> + <title>To Kill a Mockingbird</title> + <author>Harper Lee</author> + <publication_year>1960</publication_year> + </book> + </books> + <address> + <street>123 Library Lane</street> + <city>Booktown</city> + <zip>90210</zip> + </address> +</library> |