#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("1.0"); xmlNodePtr root_node = xmlNewNode(NULL, "channel"); xmlDocSetRootElement(doc, root_node); /* Set the channel name. */ xmlNewChild(root_node, NULL, "name", channel->name); /* Add lines. */ xmlNodePtr lines_node = xmlNewChild(root_node, NULL, "lines", NULL); for(int h = 0; h < 24; h++) { xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, "hour", NULL); for(int q = 0; q < 4; q++) { char s[0xf]; snprintf(s, 0xf, "%d", channel->hours[h*4 + q]); xmlNewChild(hour_node, NULL, "quarter", s); } } /* Add users. */ xmlNodePtr users_node = xmlNewChild(root_node, NULL, "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, "user", NULL); xmlNewChild(user_node, NULL, "nick", user->nick); snprintf(s, 0xf, "%d", user->words); xmlNewChild(user_node, NULL, "words", s); snprintf(s, 0xf, "%d", user->characters); xmlNewChild(user_node, NULL, "characters", s); snprintf(s, 0xf, "%d", user->kicks); xmlNewChild(user_node, NULL, "kicks", s); snprintf(s, 0xf, "%d", user->kicked); xmlNewChild(user_node, NULL, "kicked", s); snprintf(s, 0xf, "%d", user->monolog_lines); xmlNewChild(user_node, NULL, "monolog_lines", s); snprintf(s, 0xf, "%d", user->monologs); xmlNewChild(user_node, NULL, "monologs", s); /* Add lines for this user. */ xmlNodePtr lines_node = xmlNewChild(user_node, NULL, "lines", NULL); for(int h = 0; h < 24; h++) { xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, "hour", NULL); for(int q = 0; q < 4; q++) { snprintf(s, 0xf, "%d", user->lines[h*4 + q]); xmlNewChild(hour_node, NULL, "quarter", s); } } user = user->next; } } /* Add words. */ xmlNodePtr words_node = xmlNewChild(root_node, NULL, "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, "word", NULL); xmlNewChild(word_node, NULL, "name", word->name); snprintf(s, 0xf, "%d", word->count); xmlNewChild(word_node, NULL, "count", 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; }