3 #include <libxml/parser.h>
7 #include <unordered_map>
13 virtual void process(xmlNode *node, bool clean) = 0;
16 class Replace : public Directive {
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());
27 class Substitute : public Directive {
29 Substitute(const unordered_map<string, Directive*> &substitution_map)
30 : substitution_map(substitution_map) {}
32 virtual void process(xmlNode *node, bool clean) {
33 for (xmlNode *child = node->children; child != NULL; child = child->next) {
34 bool processed = false;
36 if (child->type == XML_ELEMENT_NODE) {
37 // Find the ID, if any.
39 for (xmlAttr *attr = child->properties; attr != NULL; attr = attr->next) {
40 if (strcmp(reinterpret_cast<const char *>(attr->ns->href), "http://template.sesse.net/") == 0 &&
41 strcmp(reinterpret_cast<const char *>(attr->name), "id") == 0) {
42 id = reinterpret_cast<const char *>(xmlNodeGetContent(attr->children));
46 // Check all substitutions to see if we found anything appropriate.
47 for (auto it : substitution_map) {
48 if (it.first == reinterpret_cast<const char *>(child->name) ||
49 (!id.empty() && it.first == ("#" + id))) {
50 it.second->process(child, clean);
58 process(child, clean);
64 const unordered_map<string, Directive*> &substitution_map;
67 int main(int argc, char **argv)
71 unordered_map<string, Directive*> master_map;
72 master_map.insert(make_pair("title", new Replace("A very basic example")));
73 master_map.insert(make_pair("#hello", new Replace("Hello world!")));
75 xmlDocPtr doc = xmlParseFile(argv[1]);
76 Substitute(master_map).process(xmlDocGetRootElement(doc), false);
77 xmlSaveFile("out.xml", doc);