summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--main.c140
-rw-r--r--test.xml24
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 $<
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..bd5651c
--- /dev/null
+++ b/main.c
@@ -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>