diff --git a/BaseLib/ConfigTreeUtil.cpp b/BaseLib/ConfigTreeUtil.cpp
index 79e3631c43e52dec4ead229c9b4e6c01cd125c0f..f2831a98751930e2f3ecf1a53425187e6b72b259 100644
--- a/BaseLib/ConfigTreeUtil.cpp
+++ b/BaseLib/ConfigTreeUtil.cpp
@@ -10,6 +10,7 @@
 
 #include "ConfigTreeUtil.h"
 
+#include <boost/bind.hpp>
 #include <boost/property_tree/xml_parser.hpp>
 #include <regex>
 
@@ -43,19 +44,70 @@ void ConfigTreeTopLevel::checkAndInvalidate()
     ::BaseLib::checkAndInvalidate(_ctree);
 }
 
-// From https://stackoverflow.com/a/1567703/80480
-class Line
+// Adapted from
+// https://stackoverflow.com/questions/8154107/how-do-i-merge-update-a-boostproperty-treeptree/8175833
+template <typename T>
+void traverse_recursive(boost::property_tree::ptree& parent,
+                        const boost::property_tree::ptree::path_type& childPath,
+                        boost::property_tree::ptree& child,
+                        const fs::path benchDir,
+                        T& method)
 {
-    std::string data;
+    using boost::property_tree::ptree;
 
-public:
-    friend std::istream& operator>>(std::istream& is, line& l)
+    method(parent, childPath, child, benchDir);
+    for (ptree::iterator it = child.begin(); it != child.end(); ++it)
     {
-        std::getline(is, l.data);
-        return is;
+        ptree::path_type curPath = childPath / ptree::path_type(it->first);
+        traverse_recursive(child, curPath, it->second, benchDir, method);
     }
-    operator std::string() const { return data; }
-};
+}
+
+template <typename T>
+void traverse(boost::property_tree::ptree& parent, const fs::path benchDir,
+              T& method)
+{
+    traverse_recursive(parent, "", parent, benchDir, method);
+}
+
+void replace_includes(
+    [[maybe_unused]] const boost::property_tree::ptree& parent,
+    [[maybe_unused]] const boost::property_tree::ptree::path_type& childPath,
+    boost::property_tree::ptree& child,
+    const fs::path benchDir)
+{
+    using boost::property_tree::ptree;
+    for (ptree::const_iterator it = child.begin(); it != child.end(); ++it)
+    {
+        if (it->first == "include")
+        {
+            auto filename = it->second.get<std::string>("<xmlattr>.file");
+            auto filepath = fs::path(filename);
+            if (filepath.is_relative())
+            {
+                filename = (benchDir / filepath).string();
+            }
+            INFO("Including {:s} into project file.", filename);
+
+            ptree includeTree;
+            read_xml(filename, includeTree,
+                     boost::property_tree::xml_parser::no_comments |
+                         boost::property_tree::xml_parser::trim_whitespace);
+
+            // Can only insert subtree at child
+            auto& tmpTree = child.put_child("include", includeTree);
+
+            // Move subtree above child
+            std::move(tmpTree.begin(), tmpTree.end(), back_inserter(child));
+
+            // Erase child
+            child.erase("include");
+
+            // There can only be one include under a parent element!
+            break;
+        }
+    }
+}
 
 ConfigTreeTopLevel makeConfigTree(const std::string& filepath,
                                   const bool be_ruthless,
@@ -67,38 +119,14 @@ ConfigTreeTopLevel makeConfigTree(const std::string& filepath,
     //       for our configuration tree implementation to work!
     try
     {
-        // Searching for <include filename=".." /> - tags and replacing by the
-        // content of the included file.
-        std::ifstream file(filepath);
-        std::stringstream output;
-
-        std::transform(
-            std::istream_iterator<Line>(file),
-            std::istream_iterator<Line>(),
-            std::ostream_iterator<std::string>(output, "\n"),
-            [](std::string const& _line) {
-                const std::regex base_regex(".*<include file=\"(.*)\" ?/>.*");
-                std::smatch base_match;
-                if (std::regex_match(_line, base_match, base_regex))
-                {
-                    if (base_match.size() == 2)
-                    {
-                        std::string include_filename = base_match[1].str();
-                        std::ifstream include_file(include_filename);
-                        std::string include_content(
-                            (std::istreambuf_iterator<char>(include_file)),
-                            (std::istreambuf_iterator<char>()));
-                        INFO("Including {:s} into project file.",
-                             include_filename);
-                        return include_content;
-                    }
-                }
-                return _line;
-            });
-
-        read_xml(output, ptree,
+        read_xml(filepath, ptree,
                  boost::property_tree::xml_parser::no_comments |
                      boost::property_tree::xml_parser::trim_whitespace);
+
+        if (toplevel_tag == "OpenGeoSysProject")
+        {
+            traverse(ptree, fs::path(filepath).parent_path(), replace_includes);
+        }
     }
     catch (boost::property_tree::xml_parser_error const& e)
     {