summaryrefslogtreecommitdiff
path: root/export_xml.c
blob: f7509c3b2f57c183c62e01769ca70d1c86630b01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <libxml/tree.h>
#include <libxml/xmlsave.h>
#include <string.h>

#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 <NULL> (filtered nicks eg. bots). */
			if(strcmp(user->nick, "<NULL>") == 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);

			/* 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;
}