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 xmlElement *elem = reinterpret_cast<xmlElement *>(child);
39 // Find the ID, if any.
42 for (xmlAttribute *attr = elem->attributes; attr != NULL; attr = attr->nexth) {
44 if (strcmp(reinterpret_cast<const char *>(attr->name), "id") != 0) {
47 id = xmlNodeGetContent(attr->content);
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);
63 process(child, clean);
69 const unordered_map<string, Directive*> &substitution_map;
72 int main(int argc, char **argv)
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!")));
80 xmlDocPtr doc = xmlParseFile(argv[1]);
81 Substitute(master_map).process(xmlDocGetRootElement(doc), false);
82 xmlSaveFile("out.xml", doc);