]> git.sesse.net Git - xml-template/blobdiff - c++11/xml-template.cpp
Update the PHP SWIG version to PHP 7, with various crash fixes, too.
[xml-template] / c++11 / xml-template.cpp
index 317a561779fab53a7177d8376e1bbd37de585909..bf6c085052356e0729c1f73600fcff36e13de4c7 100644 (file)
@@ -1,5 +1,6 @@
 #include "xml-template.h"
 
+#include <assert.h>
 #include <string.h>
 #include <libxml/parser.h>
 
@@ -14,12 +15,11 @@ void clean_node(xmlNode *node)
        }
        if (node->ns != NULL &&
            strcmp(reinterpret_cast<const char *>(node->ns->href), "http://template.sesse.net/") == 0) {
-               xmlNode *frag = xmlNewDocFragment(node->doc);
-               xmlReplaceNode(node, frag);
-               frag->children = node->children;
-               frag->last = node->last;
+               while (node->children != NULL) {
+                       xmlAddPrevSibling(node, node->children);
+               }
 
-               node->children = node->last = NULL;
+               xmlUnlinkNode(node);
                xmlFreeNode(node);
        }
 }
@@ -145,6 +145,7 @@ Alternate::Alternate(const string &attribute,
                        continue;
                }
                string value = alternatives[jx++ % alternatives.size()];
+               Replace *r = new Replace { value };
                subdirectives_subs[ix]->substitution_map.insert(make_pair(
                        attribute,
                        new Replace { value }));
@@ -168,8 +169,8 @@ void Substitute::process(xmlNode *node, bool clean)
 {
        xmlNode *next_child;
        for (xmlNode *child = node->children; child != NULL; child = next_child) {
-               next_child = child->next;       
-               bool processed = false;
+               next_child = child->next;
+               Directive *next_processor = this;
 
                if (child->type == XML_ELEMENT_NODE) {
                        // Find the ID, if any.
@@ -190,40 +191,36 @@ void Substitute::process(xmlNode *node, bool clean)
                        }
 
                        // Check all substitutions to see if we found anything appropriate.
+                       string tag = reinterpret_cast<const char *>(child->name);
                        for (auto it : substitution_map) {
-                               string tag = reinterpret_cast<const char *>(child->name);
-
+                               assert(it.second != nullptr);
                                // Attribute substitution.
                                if (begins_with(it.first, tag + "/")) {
+                                       string contents = it.second->get_contents();
                                        const xmlChar *attr_key = reinterpret_cast<const xmlChar *>(
                                                it.first.c_str() + tag.size() + 1);
                                        const xmlChar *attr_value = reinterpret_cast<const xmlChar *>(
-                                               it.second->get_contents().c_str());
+                                               contents.c_str());
                                        xmlSetProp(child, attr_key, attr_value);
                                } else if ((!id.empty() && begins_with(it.first, "#" + id + "/"))) {
+                                       string contents = it.second->get_contents();
                                        const xmlChar *attr_key = reinterpret_cast<const xmlChar *>(
-                                               it.first.c_str() + tag.size() + 2);
+                                               it.first.c_str() + id.size() + 2);
                                        const xmlChar *attr_value = reinterpret_cast<const xmlChar *>(
-                                               it.second->get_contents().c_str());
+                                               contents.c_str());
                                        xmlSetProp(child, attr_key, attr_value);
                                }
 
-                               if (processed) {
-                                       continue;
-                               }
-
-                               // Regular substitution.
+                               // Regular substitution. (Don't call process() immediately, because
+                               // that might delete the element, which would cause problems.)
                                if (it.first == tag ||
                                    (!id.empty() && it.first == ("#" + id))) {
-                                       it.second->process(child, clean);
-                                       processed = true;
+                                       next_processor = it.second;
                                }
                        }
                }
 
-               if (!processed) {
-                       process(child, clean);
-               }
+               next_processor->process(child, clean);
        }
        if (clean) {
                clean_node(node);