#include #include #include #include "export_xml.h" #include "word.h" #if !defined(LIBXML_TREE_ENABLED) #error "libxml must be compiled with tree 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); /* Set the channel name. */ xmlNewChild(root_node, NULL, (const xmlChar*)"name", (const xmlChar*)channel->name); /* Add lines. */ xmlNodePtr lines_node = xmlNewChild(root_node, NULL, (const xmlChar*)"lines", NULL); for(int h = 0; h < 24; h++) { xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, (const xmlChar*)"hour", NULL); 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); } } /* Add users. */ xmlNodePtr users_node = xmlNewChild(root_node, NULL, (const xmlChar*)"users", NULL); for(int u = 0; u < USERS_MAX; u++) { struct user_t *user = &users[u]; /* Iterate while we have a user (nick is non-NULL). */ while(user && user->nick) { /* Skip (filtered nicks eg. bots). */ if(strcmp(user->nick, "") == 0) { 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); /* Add lines for this user. */ xmlNodePtr lines_node = xmlNewChild(user_node, NULL, (const xmlChar*)"lines", NULL); for(int h = 0; h < 24; h++) { xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, (const xmlChar*)"hour", NULL); 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); } } user = user->next; } } /* Add words. */ xmlNodePtr words_node = xmlNewChild(root_node, NULL, (const xmlChar*)"words", NULL); 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); 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); word = word->next; } } 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; }