]> git.sesse.net Git - xml-template/blob - c++0x/xml-template.cpp
Implement cloning for C++0x.
[xml-template] / c++0x / xml-template.cpp
1 #include "xml-template.h"
2
3 #include <string.h>
4 #include <libxml/parser.h>
5
6 using namespace std;
7
8 Replace::Replace(const string &str)
9         : str(str) {}
10
11 void Replace::process(xmlNode *node, bool clean) {
12         node->children = xmlNewTextLen(reinterpret_cast<const xmlChar *>(str.data()), str.size());
13 }
14
15 Clone::Clone(const std::vector<Directive *> &subdirectives)
16         : subdirectives(subdirectives) {}
17
18 void Clone::process(xmlNode *node, bool clean) {
19         // We can't use xmlNewDocFragment, since xmlDOMWrapCloneNode only knows
20         // how to clone elements.
21         vector<xmlNode *> new_nodes;
22
23         for (auto it : subdirectives) {
24                 xmlDOMWrapCtxt ctx;
25                 xmlNode *new_node;
26                 int ret = xmlDOMWrapCloneNode(NULL, node->doc, node, &new_node, node->doc, NULL, 1, 0);
27                 it->process(new_node, clean);
28                 for (xmlNode *child = new_node->children; child != NULL; child = child->next) {
29                         new_nodes.push_back(child);
30                 }
31         }
32
33         node->children = NULL;
34         for (auto child : new_nodes) {
35                 xmlAddChild(node, child);
36         }       
37 }
38
39 Substitute::Substitute(const unordered_map<string, Directive*> &substitution_map)
40         : substitution_map(substitution_map) {}
41
42 void Substitute::process(xmlNode *node, bool clean) {
43         for (xmlNode *child = node->children; child != NULL; child = child->next) {
44                 bool processed = false;
45
46                 if (child->type == XML_ELEMENT_NODE) {
47                         // Find the ID, if any.
48                         string id;
49                         for (xmlAttr *attr = child->properties; attr != NULL; attr = attr->next) {
50                                 if (strcmp(reinterpret_cast<const char *>(attr->ns->href), "http://template.sesse.net/") == 0 &&
51                                     strcmp(reinterpret_cast<const char *>(attr->name), "id") == 0) {
52                                         id = reinterpret_cast<const char *>(xmlNodeGetContent(attr->children));
53
54                                         if (clean) {
55                                                 if (attr->prev == NULL) {
56                                                         child->properties = attr->next;
57                                                 } else {
58                                                         attr->prev->next = attr->next;
59                                                 }
60                                         }
61                                 }
62                         }
63
64                         // Check all substitutions to see if we found anything appropriate.
65                         for (auto it : substitution_map) {
66                                 if (it.first == reinterpret_cast<const char *>(child->name) ||
67                                     (!id.empty() && it.first == ("#" + id))) {
68                                         it.second->process(child, clean);
69                                         processed = true;
70                                         break;
71                                 }
72                         }
73                 }
74                 
75                 if (!processed) {
76                         process(child, clean);
77                 }
78         }
79 }
80         
81 void process_file(const string &input_filename,
82                   const string &output_filename,
83                   Directive *root_directive)
84 {
85         LIBXML_TEST_VERSION
86
87         xmlDocPtr doc = xmlParseFile(input_filename.c_str());
88         root_directive->process(xmlDocGetRootElement(doc), true);
89         xmlSaveFile(output_filename.c_str(), doc);
90
91         xmlCleanupParser();
92         xmlMemoryDump();
93 }