diff options
-rw-r--r-- | export_xml.c | 128 |
1 files changed, 78 insertions, 50 deletions
diff --git a/export_xml.c b/export_xml.c index 7bc9c3d..1bed18b 100644 --- a/export_xml.c +++ b/export_xml.c @@ -1,37 +1,45 @@ -#include <libxml/tree.h> -#include <libxml/xmlsave.h> +#include <libxml/xmlwriter.h> #include <string.h> #include "export_xml.h" #include "word.h" -#if !defined(LIBXML_TREE_ENABLED) -#error "libxml must be compiled with tree support" +#if !defined(LIBXML_WRITER_ENABLED) +#error "libxml must be compiled with text writer support" #endif int export_xml(struct channel_t *channel, struct user_t *users) { /* Create document and set root node. */ - xmlDocPtr doc = xmlNewDoc((const xmlChar*)"1.0"); - xmlNodePtr root_node = xmlNewNode(NULL, (const xmlChar*)"channel"); - xmlDocSetRootElement(doc, root_node); + xmlTextWriterPtr writer = xmlNewTextWriterFilename(channel->xmlpath, 0); + if(writer == NULL) { + fprintf(stderr, "Failed to create text writer for filename \"%s\"\n", channel->xmlpath); + return 0; + } + + xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"channel"); /* Set the channel name. */ - xmlNewChild(root_node, NULL, (const xmlChar*)"name", (const xmlChar*)channel->name); + xmlTextWriterStartElement(writer, (const xmlChar*)"name"); + xmlTextWriterWriteString(writer, (const xmlChar*)channel->name); + xmlTextWriterEndElement(writer); /* Add lines. */ - xmlNodePtr lines_node = xmlNewChild(root_node, NULL, (const xmlChar*)"lines", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"lines"); for(int h = 0; h < 24; h++) { - xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, (const xmlChar*)"hour", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"hour"); for(int q = 0; q < 4; q++) { - char s[0xf]; - snprintf(s, 0xf, "%lu", channel->hours[h*4 + q]); - xmlNewChild(hour_node, NULL, (const xmlChar*)"quarter", (const xmlChar*)s); + xmlTextWriterStartElement(writer, (const xmlChar*)"quarter"); + xmlTextWriterWriteFormatString(writer, "%lu", channel->hours[h*4 + q]); + xmlTextWriterEndElement(writer); } + xmlTextWriterEndElement(writer); // hour } + xmlTextWriterEndElement(writer); // lines /* Add users. */ - xmlNodePtr users_node = xmlNewChild(root_node, NULL, (const xmlChar*)"users", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"users"); for(int u = 0; u < USERS_MAX; u++) { struct user_t *user = &users[u]; /* Iterate while we have a user (nick is non-NULL). */ @@ -41,61 +49,81 @@ int export_xml(struct channel_t *channel, struct user_t *users) { user = user->next; continue; } - char s[0xf]; - xmlNodePtr user_node = xmlNewChild(users_node, NULL, (const xmlChar*)"user", NULL); - - xmlNewChild(user_node, NULL, (const xmlChar*)"nick", (xmlChar*)user->nick); - snprintf(s, 0xf, "%llu", user->words); - xmlNewChild(user_node, NULL, (const xmlChar*)"words", (const xmlChar*)s); - snprintf(s, 0xf, "%llu", user->characters); - xmlNewChild(user_node, NULL, (const xmlChar*)"characters", (const xmlChar*)s); - snprintf(s, 0xf, "%llu", user->kicks); - xmlNewChild(user_node, NULL, (const xmlChar*)"kicks", (const xmlChar*)s); - snprintf(s, 0xf, "%llu", user->kicked); - xmlNewChild(user_node, NULL, (const xmlChar*)"kicked", (const xmlChar*)s); - snprintf(s, 0xf, "%llu", user->monolog_lines); - xmlNewChild(user_node, NULL, (const xmlChar*)"monolog_lines", (const xmlChar*)s); - snprintf(s, 0xf, "%llu", user->monologs); - xmlNewChild(user_node, NULL, (const xmlChar*)"monologs", (const xmlChar*)s); + xmlTextWriterStartElement(writer, (const xmlChar*)"user"); + + xmlTextWriterStartElement(writer, (const xmlChar*)"nick"); + xmlTextWriterWriteString(writer, (const xmlChar*)user->nick); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"words"); + xmlTextWriterWriteFormatString(writer, "%llu", user->words); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"characters"); + xmlTextWriterWriteFormatString(writer, "%llu", user->characters); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"kicks"); + xmlTextWriterWriteFormatString(writer, "%llu", user->kicks); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"kicked"); + xmlTextWriterWriteFormatString(writer, "%llu", user->kicked); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"monolog_lines"); + xmlTextWriterWriteFormatString(writer, "%llu", user->monolog_lines); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"monologs"); + xmlTextWriterWriteFormatString(writer, "%llu", user->monologs); + xmlTextWriterEndElement(writer); /* Add lines for this user. */ - xmlNodePtr lines_node = xmlNewChild(user_node, NULL, (const xmlChar*)"lines", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"lines"); for(int h = 0; h < 24; h++) { - xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, (const xmlChar*)"hour", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"hour"); for(int q = 0; q < 4; q++) { - snprintf(s, 0xf, "%lu", user->lines[h*4 + q]); - xmlNewChild(hour_node, NULL, (const xmlChar*)"quarter", (const xmlChar*)s); + xmlTextWriterStartElement(writer, (const xmlChar*)"quarter"); + xmlTextWriterWriteFormatString(writer, "%lu", user->lines[h*4 + q]); + xmlTextWriterEndElement(writer); } + xmlTextWriterEndElement(writer); // hour } + xmlTextWriterEndElement(writer); // lines user = user->next; + + xmlTextWriterEndElement(writer); // user } } + xmlTextWriterEndElement(writer); // users /* Add words. */ - xmlNodePtr words_node = xmlNewChild(root_node, NULL, (const xmlChar*)"words", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"words"); for(int w = 0; w < WORDS_MAX; w++) { struct word_t *word = &words[w]; while(word && word->name) { - char s[0xf]; - xmlNodePtr word_node = xmlNewChild(words_node, NULL, (const xmlChar*)"word", NULL); + xmlTextWriterStartElement(writer, (const xmlChar*)"word"); - xmlNewChild(word_node, NULL, (const xmlChar*)"name", (const xmlChar*)word->name); - snprintf(s, 0xf, "%llu", word->count); - xmlNewChild(word_node, NULL, (const xmlChar*)"count", (const xmlChar*)s); + xmlTextWriterStartElement(writer, (const xmlChar*)"name"); + xmlTextWriterWriteString(writer, (const xmlChar*)word->name); + xmlTextWriterEndElement(writer); + + xmlTextWriterStartElement(writer, (const xmlChar*)"count"); + xmlTextWriterWriteFormatString(writer, "%llu", word->count); + xmlTextWriterEndElement(writer); word = word->next; + + xmlTextWriterEndElement(writer); // word } } + xmlTextWriterEndElement(writer); // words + + xmlTextWriterEndElement(writer); // channel + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); - xmlSaveCtxtPtr save_context = xmlSaveToFilename(channel->xmlpath, "UTF-8", 0); - if(!save_context) { - xmlErrorPtr error = xmlGetLastError(); - fprintf(stderr, "Failed to save XML data: %s\n", (error ? error->message : "unknown error")); - xmlFreeDoc(doc); - return 0; - } - xmlSaveDoc(save_context, doc); - xmlSaveClose(save_context); - xmlFreeDoc(doc); return 1; } |