]> git.sesse.net Git - xml-template/blob - c++0x/simple.cpp
a5e7894ccfe0d66cc82d61dfe97b68bd884b96a9
[xml-template] / c++0x / simple.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <libxml/parser.h>
4
5 #include <string>
6 #include <utility>
7 #include <unordered_map>
8
9 using namespace std;
10
11 class Directive {
12  public:
13         virtual void process(xmlNode *node, bool clean) = 0;
14 };
15
16 class Replace : public Directive {
17  public:
18         Replace(const string &str) : str(str) {}
19         virtual void process(xmlNode *node, bool clean) {
20                 node->children = xmlNewTextLen(reinterpret_cast<const xmlChar *>(str.data()), str.size());
21         }
22
23  private:
24         const string str;
25 };
26
27 class Substitute : public Directive {
28  public:
29         Substitute(const unordered_map<string, Directive*> &substitution_map)
30                 : substitution_map(substitution_map) {}
31
32         virtual void process(xmlNode *node, bool clean) {
33                 for (xmlNode *child = node->children; child != NULL; child = child->next) {
34                         bool processed = false;
35
36                         if (child->type == XML_ELEMENT_NODE) {
37                                 xmlElement *elem = reinterpret_cast<xmlElement *>(child);
38
39                                 // Find the ID, if any.
40                                 string id;
41 #if 0
42                                 for (xmlAttribute *attr = elem->attributes; attr != NULL; attr = attr->nexth) {
43                                         // FIXME: namespace
44                                         if (strcmp(reinterpret_cast<const char *>(attr->name), "id") != 0) {
45                                                 continue;
46                                         }
47                                         id = xmlNodeGetContent(attr->content);
48                                 }
49 #endif
50
51                                 // Check all substitutions to see if we found anything appropriate.
52                                 for (auto it : substitution_map) {
53                                         if (it.first == reinterpret_cast<const char *>(child->name) ||
54                                             (!id.empty() && ("#" + it.first) == id)) {
55                                                 it.second->process(child, clean);
56                                                 processed = true;
57                                                 break;
58                                         }
59                                 }
60                         }
61                         
62                         if (!processed) {
63                                 process(child, clean);
64                         }
65                 }
66         }
67
68  private:
69         const unordered_map<string, Directive*> &substitution_map;
70 };
71
72 int main(int argc, char **argv)
73 {
74         LIBXML_TEST_VERSION
75
76         unordered_map<string, Directive*> master_map;
77         master_map.insert(make_pair("title", new Replace("A very basic example")));
78         master_map.insert(make_pair("#hello", new Replace("Hello world!")));
79
80         xmlDocPtr doc = xmlParseFile(argv[1]);
81         Substitute(master_map).process(xmlDocGetRootElement(doc), false);
82         xmlSaveFile("out.xml", doc);
83
84         xmlCleanupParser();
85         xmlMemoryDump();
86         return(0);
87 }