]> git.sesse.net Git - xml-template/blob - c++0x/simple.cpp
Fix #id handling in the C++0x version.
[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                                 // Find the ID, if any.
38                                 string id;
39                                 for (xmlAttr *attr = child->properties; attr != NULL; attr = attr->next) {
40                                         // FIXME: namespace
41                                         if (strcmp(reinterpret_cast<const char *>(attr->name), "id") != 0) {
42                                                 continue;
43                                         }
44                                         id = reinterpret_cast<const char *>(xmlNodeGetContent(attr->children));
45                                 }
46
47                                 // Check all substitutions to see if we found anything appropriate.
48                                 for (auto it : substitution_map) {
49                                         if (it.first == reinterpret_cast<const char *>(child->name) ||
50                                             (!id.empty() && it.first == ("#" + id))) {
51                                                 it.second->process(child, clean);
52                                                 processed = true;
53                                                 break;
54                                         }
55                                 }
56                         }
57                         
58                         if (!processed) {
59                                 process(child, clean);
60                         }
61                 }
62         }
63
64  private:
65         const unordered_map<string, Directive*> &substitution_map;
66 };
67
68 int main(int argc, char **argv)
69 {
70         LIBXML_TEST_VERSION
71
72         unordered_map<string, Directive*> master_map;
73         master_map.insert(make_pair("title", new Replace("A very basic example")));
74         master_map.insert(make_pair("#hello", new Replace("Hello world!")));
75
76         xmlDocPtr doc = xmlParseFile(argv[1]);
77         Substitute(master_map).process(xmlDocGetRootElement(doc), false);
78         xmlSaveFile("out.xml", doc);
79
80         xmlCleanupParser();
81         xmlMemoryDump();
82         return(0);
83 }