diff --git a/CMakeLists.txt b/CMakeLists.txt
index c91030a4b89e3cc148a25a4ce699dfdefd7b1e23..ca9ce75f71c23c8d481cb85a675189111d78fa96 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,7 +76,7 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
     add_compile_options(-Wno-error=unused-but-set-variable)
     add_compile_options(-Wno-error=unused-variable)
     add_compile_options(-Wno-error=unused-parameter)
-    add_compile_options(-Wno-error=deprecated)
+    add_compile_options(-Wno-error=deprecated-declarations)
 endif()
 
 #######################################################################################
@@ -89,12 +89,13 @@ OPTION(Simox_USE_OPENSCENEGRAPH_VISUALIZATION "Use OpenSceneGraph for visualizat
 OPTION(Simox_COLLISION_CHECKER_PQP "Build and use the PQP Collision Detection library (located in ExternalDependencies)" ON)
 #######################################################################################
 MESSAGE(STATUS "******************** Configuring Simox ************************")
+set (Simox_BUILD_VirtualRobot TRUE CACHE BOOL "Build Virtual Robot library")
 set (Simox_BUILD_Saba TRUE CACHE BOOL "Build Motion Planning library")
 set (Simox_BUILD_GraspStudio TRUE CACHE BOOL "Build Grasp Planning library")
 set (Simox_BUILD_SimDynamics TRUE CACHE BOOL "Build Dynamic Simulation")
 
 MESSAGE (STATUS "** SIMOX BUILD SimoxUtility: TRUE (can't be turned off)")
-MESSAGE (STATUS "** SIMOX BUILD VirtualRobot: TRUE (can't be turned off)")
+MESSAGE (STATUS "** SIMOX BUILD VirtualRobot: ${Simox_BUILD_VirtualRobot}")
 MESSAGE (STATUS "** SIMOX BUILD Saba        : ${Simox_BUILD_Saba}")
 MESSAGE (STATUS "** SIMOX BUILD GraspStudio : ${Simox_BUILD_GraspStudio}")
 MESSAGE (STATUS "** SIMOX BUILD SimDynamics : ${Simox_BUILD_SimDynamics}")
@@ -194,13 +195,15 @@ endif()
 
 #######################################################################################
 add_subdirectory(SimoxUtility)
-add_subdirectory(VirtualRobot)
-
+list (APPEND SIMOX_EXPORT_TARGET_LIST SimoxUtility)
+list (APPEND Simox_LIBRARIES          SimoxUtility)
 
 #######################################################################################
-list (APPEND SIMOX_EXPORT_TARGET_LIST SimoxUtility VirtualRobot)
-list (APPEND Simox_LIBRARIES          SimoxUtility VirtualRobot)
-
+if (Simox_BUILD_VirtualRobot)
+    add_subdirectory(VirtualRobot)
+    list(APPEND SIMOX_EXPORT_TARGET_LIST VirtualRobot)
+    list(APPEND Simox_LIBRARIES VirtualRobot)
+endif()
 
 #######################################################################################
 if (Simox_BUILD_Saba)
diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt
index 22721c174cc9a07a91168d4199c475ed15a3c126..cbbe5d613e9bb03097b69119beffc4291a9dbf5d 100644
--- a/SimoxUtility/CMakeLists.txt
+++ b/SimoxUtility/CMakeLists.txt
@@ -50,6 +50,8 @@ MESSAGE (STATUS "\n***** CONFIGURING Simox project SimoxUtility *****")
 SET(SOURCES
     SimoxUtility.cpp
 
+    algorithm/string/string_tools.cpp
+
     color/cmaps/colormaps.cpp
     color/cmaps/Named.cpp
     color/Color.cpp
@@ -89,6 +91,9 @@ SET(INCLUDES
     algorithm/for_each_if.h
     algorithm/apply.hpp
     algorithm/get_map_keys_values.h
+    algorithm/string/string_tools.h
+    algorithm/string/string_conversion.h
+    algorithm/string/string_conversion_eigen.h
 
     color/cmaps/colormaps.h
     color/cmaps/Named.h
@@ -96,6 +101,7 @@ SET(INCLUDES
     color/Color.h
     color/ColorMap.h
     color/GlasbeyLUT.h
+    color/KellyLUT.h
     color/hsv.h
     color/interpolation.h
     color/json.h
@@ -106,6 +112,7 @@ SET(INCLUDES
 
     error/SimoxError.h
 
+    filesystem/make_relative.h
     filesystem/list_directory.h
     filesystem/remove_trailing_separator.h
 
@@ -216,6 +223,11 @@ SET(INCLUDES
     meta/enum/adapt_enum.h
     meta/enum/EnumNames.hpp
 
+    xml/rapidxml/rapidxml.hpp
+    xml/rapidxml/rapidxml_print.hpp
+    xml/rapidxml/RapidXMLWrapper.h
+    xml/rapidxml/RapidXMLForwardDecl.h
+
     shapes/AxisAlignedBoundingBox.h
     shapes/OrientedBoxBase.h
     shapes/OrientedBox.h
diff --git a/SimoxUtility/algorithm.h b/SimoxUtility/algorithm.h
index 10719420d53a3b1e3873d1a93a6b08b2210e3019..53e55e3b48d89ff17a21649b83f055116f6699c2 100644
--- a/SimoxUtility/algorithm.h
+++ b/SimoxUtility/algorithm.h
@@ -4,3 +4,4 @@
 
 #include "algorithm/for_each_if.h"
 #include "algorithm/get_map_keys_values.h"
+#include "algorithm/string.h"
diff --git a/SimoxUtility/algorithm/string.h b/SimoxUtility/algorithm/string.h
new file mode 100644
index 0000000000000000000000000000000000000000..30178e410dcaf690eac928eaacabff26d658112a
--- /dev/null
+++ b/SimoxUtility/algorithm/string.h
@@ -0,0 +1,7 @@
+#pragma once
+
+// This file is generated!
+
+#include "string/string_conversion.h"
+#include "string/string_conversion_eigen.h"
+#include "string/string_tools.h"
diff --git a/SimoxUtility/algorithm/string/string_conversion.h b/SimoxUtility/algorithm/string/string_conversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..857abdf9480d2c8efac498c2552695ac32fe924b
--- /dev/null
+++ b/SimoxUtility/algorithm/string/string_conversion.h
@@ -0,0 +1,143 @@
+/**
+ * This file is part of Simox.
+ *
+ * Simox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Simox is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Andre Meixner (andre dot meixner at kit dot edu)
+ * @copyright  2020 Andre Meixner
+ *             GNU Lesser General Public License
+ */
+
+#pragma once
+
+#include <type_traits>
+#include <iomanip>
+
+#include "SimoxUtility/error.h"
+#include "string_tools.h"
+
+namespace simox::alg {
+    namespace help {
+        template <typename T>
+        struct type{};
+
+        template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+        inline T to_(const std::string& s, type<T>, std::locale locale = DEFAULT_LOCALE, bool trim = true)
+        {
+            char c;
+            std::stringstream ss;
+            ss.imbue(locale);
+            if (trim)
+                ss << alg::trim_copy(s);
+            else
+                ss << s;
+            T value;
+            ss >> value;
+            if (ss.fail() || ss.get(c)) {
+                throw error::SimoxError("Cannot convert string " + s + " to " + typeid(T).name());
+                ss.clear();
+            }
+            return value;
+        }
+
+        template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+        inline T to_(const std::string& s, type<bool>, std::locale /*locale*/, bool trim = true)
+        {
+            std::string help = to_lower(s);
+            if (trim) alg::trim(help);
+            if (help == "true" || help == "1") return true;
+            else if (help == "false" || help == "0") return false;
+            else throw error::SimoxError("Cannot convert string " + s + " to boolean.");
+        }
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    inline T to_(const std::string& s, std::locale locale = DEFAULT_LOCALE, bool trim = true)
+    {
+        return help::to_<T>(s, help::type<T>{}, locale, trim);
+    }
+
+    template<typename T, typename std::enable_if<!std::is_integral<T>::value>::type* = nullptr>
+    inline std::vector<T> to_vec(const std::vector<std::string>& vec, std::locale locale = DEFAULT_LOCALE, bool trimElements = false)
+    {
+        std::vector<T> res;
+        for (const std::string& str : vec)
+        {
+            res.push_back(to_<T>(str, locale, trimElements));
+        }
+        return res;
+    }
+
+    template<typename T, typename std::enable_if<!std::is_integral<T>::value>::type* = nullptr>
+    inline std::vector<T> to_vec(const std::string& str, const std::string& splitBy = "\t ", bool trimElements = true,
+                                 bool ignoreEmptyElements = true, std::locale locale = DEFAULT_LOCALE)
+    {
+        return to_vec<T>(split(str, splitBy, trimElements, ignoreEmptyElements, locale), locale, false);
+    }
+
+    template<typename T, typename std::enable_if<!std::is_integral<T>::value>::type* = nullptr>
+    inline std::vector<T> to_vec_check_size(const std::string& str, unsigned int expectedSize, const std::string& splitBy = "\t ",
+                                       bool trimElements = true, bool ignoreEmptyElements = true, std::locale locale = DEFAULT_LOCALE)
+    {
+        return to_vec<T>(split_check_size(str, expectedSize, splitBy, trimElements, ignoreEmptyElements, locale), locale, false);
+    }
+
+
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    inline std::string to_string(T x, const std::locale& locale = DEFAULT_LOCALE)
+    {
+        std::stringstream ss;
+        ss.imbue(locale);
+        ss << x;
+        return ss.str();
+    }
+
+    template<> inline std::string to_string<double>(double d,  const std::locale& locale)
+    {
+        std::stringstream ss;
+        ss.imbue(locale);
+        ss << std::setprecision(12) << d;
+        return ss.str();
+    }
+
+    template<> inline std::string to_string<bool>(bool x, const std::locale& /*locale*/)
+    {
+        return x ? "true" : "false";
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    inline std::string to_string(const std::vector<T>& vec, const std::string& splitBy = " ", std::locale locale = DEFAULT_LOCALE)
+    {
+        std::stringstream stream;
+         stream.imbue(locale);
+        for(unsigned int i = 0; i < vec.size(); ++i) {
+            stream << to_string(vec.at(i));
+            if (i + 1 != vec.size()) stream << splitBy;
+        }
+        return stream.str();
+    }
+
+    template<typename T, typename std::enable_if<!std::is_fundamental<T>::value>::type* = nullptr>
+    inline std::string to_string(const std::vector<T>& vec, const std::string& splitBy = " ", std::locale locale = DEFAULT_LOCALE)
+    {
+        std::stringstream stream;
+        stream.imbue(locale);
+        for(unsigned int i = 0; i < vec.size(); ++i) {
+            stream << vec.at(i);
+            if (i + 1 != vec.size()) stream << splitBy;
+        }
+        return stream.str();
+    }
+}
diff --git a/SimoxUtility/algorithm/string/string_conversion_eigen.h b/SimoxUtility/algorithm/string/string_conversion_eigen.h
new file mode 100644
index 0000000000000000000000000000000000000000..864fa7f236bfdf68710694fac886d2dbcfb26c7e
--- /dev/null
+++ b/SimoxUtility/algorithm/string/string_conversion_eigen.h
@@ -0,0 +1,74 @@
+/**
+ * This file is part of Simox.
+ *
+ * Simox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Simox is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Andre Meixner (andre dot meixner at kit dot edu)
+ * @copyright  2020 Andre Meixner
+ *             GNU Lesser General Public License
+ */
+
+#pragma once
+
+#include <Eigen/Core>
+
+#include "string_conversion.h"
+
+namespace simox::alg {
+    template<typename T, int Rows = Eigen::Dynamic, typename std::enable_if<!std::is_integral<T>::value>::type* = nullptr>
+    inline Eigen::Matrix<T, Rows, 1> to_eigen(const std::vector<std::string>& vec, std::locale locale = DEFAULT_LOCALE, bool trimElements = false)
+    {
+        if (Rows != Eigen::Dynamic && Rows != (int)vec.size())
+            throw error::SimoxError("Sizes do not match!");
+        Eigen::Matrix<T, Rows, 1> res(vec.size());
+        for (unsigned int i = 0; i < vec.size(); i++)
+        {
+            res(i) = to_<T>(vec[i], locale, trimElements);
+        }
+        return res;
+    }
+
+    template<typename T = float, typename std::enable_if<std::is_scalar<T>::value>::type* = nullptr>
+    inline Eigen::Matrix<T, Eigen::Dynamic, 1> to_eigen_vec(const std::string& str, const std::string& splitBy = "\t ",
+                                                            bool trimElements = true, bool ignoreEmptyElements = true, std::locale locale = DEFAULT_LOCALE)
+    {
+        return to_eigen<T>(split(str, splitBy, trimElements, ignoreEmptyElements, locale), locale, false);
+    }
+
+    template<typename T = float, typename std::enable_if<std::is_scalar<T>::value>::type* = nullptr>
+    inline Eigen::Matrix<T, Eigen::Dynamic, 1> to_eigen_vec_check_rows(const std::string& str, int expectedRows, const std::string& splitBy = "\t ",
+                                                                       bool trimElements = true, bool ignoreEmptyElements = true, std::locale locale = DEFAULT_LOCALE)
+    {
+        return to_eigen<T>(split_check_size(str, expectedRows, splitBy, trimElements, ignoreEmptyElements, locale), locale, false);
+    }
+
+    template<typename T, unsigned int Rows, typename std::enable_if<std::is_scalar<T>::value>::type* = nullptr>
+    inline Eigen::Matrix<T, Rows, 1> to_eigen_vec(const std::string& str, const std::string& splitBy = "\t ",
+                                                  bool trimElements = true, bool ignoreEmptyElements = true, std::locale locale = DEFAULT_LOCALE)
+    {
+        return to_eigen<T, Rows>(split_check_size(str, Rows, splitBy, trimElements, ignoreEmptyElements, locale), locale, false);
+    }
+
+    template<typename T, int Rows, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
+    inline std::string to_string(const Eigen::Matrix<T, Rows, 1>& vec, const std::string& splitBy = " ", std::locale locale = DEFAULT_LOCALE)
+    {
+        std::ostringstream stream;
+        stream.imbue(locale);
+        for(unsigned int i = 0; i < vec.rows(); ++i) {
+            stream << to_string(vec(i));
+            if (i + 1 != vec.rows()) stream << splitBy;
+        }
+        return stream.str();
+    }
+}
diff --git a/SimoxUtility/algorithm/string/string_tools.cpp b/SimoxUtility/algorithm/string/string_tools.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..24f6ccf47fa4647880304cc49734108feefe64c0
--- /dev/null
+++ b/SimoxUtility/algorithm/string/string_tools.cpp
@@ -0,0 +1,79 @@
+#include "string_tools.h"
+
+#include "SimoxUtility/error/SimoxError.h"
+
+#include <algorithm>
+
+#include <iomanip>
+#include <boost/algorithm/string.hpp>
+#include <boost/bind.hpp>
+
+namespace simox::alg
+{
+
+std::string to_lower(const std::string& str)
+{
+    std::string res = str;
+    std::transform(res.begin(), res.end(), res.begin(), tolower);
+    return res;
+}
+
+void trim(std::string& str, const std::locale& locale) {
+    boost::trim(str, locale);
+}
+
+std::string trim_copy(const std::string& str, const std::locale& locale) {
+    return boost::trim_copy(str, locale);
+}
+
+void trim_if(std::string& str, const std::string& trim) {
+    boost::trim_if(str, boost::is_any_of(trim));
+}
+
+std::string trim_copy_if(std::string& str, const std::string& trim) {
+    return boost::trim_copy_if(str, boost::is_any_of(trim));
+}
+
+std::vector<std::string> split(const std::string& str, const std::string& splitBy, bool trimElements, bool removeEmptyElements, const std::locale& locale)
+{
+    std::vector<std::string> strs;
+    boost::split(strs, str, boost::is_any_of(splitBy));
+
+    if (trimElements) std::for_each(strs.begin(), strs.end(), boost::bind(&boost::trim<std::string>, _1, locale));
+
+    if (removeEmptyElements) strs.erase(std::remove_if(strs.begin(), strs.end(), [](const std::string& s) { return s.empty(); }), strs.end());
+
+    return strs;
+}
+
+std::vector<std::string> split_check_size(const std::string& str, unsigned int expectedSize, const std::string& splitBy, bool trimElements, bool removeEmptyElements, const std::locale& locale)
+{
+    std::vector<std::string> strs = split(str, splitBy, trimElements, removeEmptyElements, locale);
+
+    if (strs.size() != expectedSize)
+        throw error::SimoxError("String " + str + " contains " + std::to_string(strs.size()) + " instead of " + std::to_string(expectedSize) + " values seperated by delimiter " + splitBy);
+    return strs;
+}
+
+std::string join(const std::vector<std::string> vec, const std::string& delimiter, bool trimElements, bool ignoreEmptyElements, const std::locale& locale) {
+    std::ostringstream ss;
+    ss.imbue(locale);
+    for (size_t index = 0; index < vec.size(); index++)
+    {
+        if (trimElements)
+        {
+            std::string trimmed = trim_copy(vec.at(index), locale);
+            if (ignoreEmptyElements && trimmed.empty()) continue;
+            ss << trimmed;
+        }
+        else
+        {
+            if (ignoreEmptyElements && vec.at(index).empty()) continue;
+            ss << vec.at(index);
+        }
+        if (index != vec.size()) ss << delimiter;
+    }
+    return ss.str();
+}
+
+}
diff --git a/SimoxUtility/algorithm/string/string_tools.h b/SimoxUtility/algorithm/string/string_tools.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9df585aac83274a47a1eb210c140fb88be3f474
--- /dev/null
+++ b/SimoxUtility/algorithm/string/string_tools.h
@@ -0,0 +1,50 @@
+/**
+ * This file is part of Simox.
+ *
+ * Simox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Simox is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Andre Meixner (andre dot meixner at kit dot edu)
+ * @copyright  2020 Andre Meixner
+ *             GNU Lesser General Public License
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <locale>
+
+namespace simox::alg {
+    static std::locale DEFAULT_LOCALE = std::locale::classic();
+
+    std::string to_lower(const std::string& str);
+
+    void trim(std::string& str, const std::locale& locale = DEFAULT_LOCALE);
+
+    std::string trim_copy(const std::string& str, const std::locale& locale = DEFAULT_LOCALE);
+
+    void trim_if(std::string& str, const std::string& trim = "\t ");
+
+    std::string trim_copy_if(const std::string& str, const std::string& trim = "\t ");
+
+    std::vector<std::string> split(const std::string& str, const std::string& splitBy = "\t ", bool trimElements = true,
+                                   bool removeEmptyElements = true, const std::locale& locale = DEFAULT_LOCALE);
+
+    //! @param expectedSize throws SimoxError if split not matches expectedSize
+    std::vector<std::string> split_check_size(const std::string& str, unsigned int expectedSize, const std::string& splitBy = "\t ",
+                                         bool trimElements = true, bool removeEmptyElements = true, const std::locale& locale = DEFAULT_LOCALE);
+
+    std::string join(const std::vector<std::string> vec, const std::string& delimiter = " ", bool trimElements = false,
+                     bool ignoreEmptyElements = false, const std::locale& locale = DEFAULT_LOCALE);
+}
diff --git a/SimoxUtility/color.h b/SimoxUtility/color.h
index 8504b2340383555e7cff98673094e90e8cbb233a..fa1290568667f9b447914b158226a0ddfb10d484 100644
--- a/SimoxUtility/color.h
+++ b/SimoxUtility/color.h
@@ -5,6 +5,7 @@
 #include "color/Color.h"
 #include "color/ColorMap.h"
 #include "color/GlasbeyLUT.h"
+#include "color/KellyLUT.h"
 #include "color/cmaps.h"
 #include "color/hsv.h"
 #include "color/interpolation.h"
diff --git a/SimoxUtility/color/KellyLUT.h b/SimoxUtility/color/KellyLUT.h
new file mode 100644
index 0000000000000000000000000000000000000000..f82f218a176709014bdd3f08497f3df81432bb8a
--- /dev/null
+++ b/SimoxUtility/color/KellyLUT.h
@@ -0,0 +1,237 @@
+/*
+This file is part of MMM.
+
+MMM is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+MMM is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MMM.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @package    MMM
+* @author     Andre Meixner
+* @copyright  2020 High Performance Humanoid Technologies (H2T, 255; Karlsruhe, Germany
+*
+*/
+
+#pragma once
+
+#include "Color.h"
+#include <vector>
+#include <set>
+
+namespace simox::color
+{
+
+/**
+ * @brief 20 distinguishable colors by Kenneth L. Kelly but without black and white, e.g. usable for creating graphs
+ */
+class KellyLUT {
+public:
+    static const inline Color kelly_vivid_yellow          =   Color(0xFF, 0xB3, 0x00, 255);
+    static const inline Color kelly_strong_purple         =   Color(0x80, 0x3E, 0x75, 255);
+    static const inline Color kelly_vivid_orange          =   Color(0xFF, 0x68, 0x00, 255);
+    static const inline Color kelly_very_light_blue       =   Color(0xA6, 0xBD, 0xD7, 255);
+    static const inline Color kelly_vivid_red             =   Color(0xC1, 0x00, 0x20, 255);
+    static const inline Color kelly_grayish_yellow        =   Color(0xCE, 0xA2, 0x62, 255);
+    static const inline Color kelly_medium_gray           =   Color(0x81, 0x70, 0x66, 255);
+
+    //The following will not be good for people with defective color vision
+    static const inline Color kelly_vivid_green           =   Color(0x00, 0x7D, 0x34, 255);
+    static const inline Color kelly_strong_purplish_pink  =   Color(0xF6, 0x76, 0x8E, 255);
+    static const inline Color kelly_strong_blue           =   Color(0x00, 0x53, 0x8A, 255);
+    static const inline Color kelly_yellowish_pink        =   Color(0xFF, 0x7A, 0x5C, 255);
+    static const inline Color kelly_strong_violet         =   Color(0x53, 0x37, 0x7A, 255);
+    static const inline Color kelly_vivid_orange_yellow   =   Color(0xFF, 0x8E, 0x00, 255);
+    static const inline Color kelly_strong_purplish_red   =   Color(0xB3, 0x28, 0x51, 255);
+    static const inline Color kelly_vivid_greenish_yellow =   Color(0xF4, 0xC8, 0x00, 255);
+    static const inline Color kelly_strong_reddish_brown  =   Color(0x7F, 0x18, 0x0D, 255);
+    static const inline Color kelly_vivid_yellowish_green =   Color(0x93, 0xAA, 0x00, 255);
+    static const inline Color kelly_deep_yellowish_brown  =   Color(0x59, 0x33, 0x15, 255);
+    static const inline Color kelly_vivid_reddish_orange  =   Color(0xF1, 0x3A, 0x13, 255);
+    static const inline Color kelly_dark_olive_green      =   Color(0x23, 0x2C, 0x16, 255);
+
+    static const inline std::vector<Color> KELLY_COLORS_COLOR_BLIND =
+    {
+        kelly_vivid_yellow, kelly_strong_purple, kelly_vivid_orange, kelly_very_light_blue, kelly_vivid_red, kelly_grayish_yellow, kelly_medium_gray
+    };
+
+    static const inline std::vector<Color> KELLY_COLORS =
+    {
+        kelly_vivid_yellow, kelly_strong_purple, kelly_vivid_orange, kelly_very_light_blue, kelly_vivid_red, kelly_grayish_yellow, kelly_medium_gray,
+        kelly_vivid_green, kelly_strong_purplish_pink, kelly_strong_blue, kelly_strong_violet, kelly_strong_violet, kelly_vivid_orange_yellow,
+        kelly_strong_purplish_red, kelly_vivid_greenish_yellow, kelly_strong_reddish_brown, kelly_vivid_yellowish_green, kelly_deep_yellowish_brown,
+        kelly_vivid_reddish_orange, kelly_dark_olive_green
+    };
+
+    /**
+     * @brief Get a color from the lookup table with given ID.
+     * The ID is automaticall wrapped if greater than `size()`.
+     */
+    static Color at(std::size_t id, int alpha = 255, bool color_blind = false)
+    {
+        id = id % size(color_blind);
+        return data(color_blind).at(id).with_alpha(alpha);
+    }
+
+    /**
+     * @brief Get a color from the lookup table with given ID (with float values).
+     * The ID is automaticall wrapped if greater than `size()`.
+     */
+    static Eigen::Vector4f atf(std::size_t id, float alpha = 1.f, bool color_blind = false)
+    {
+        return at(id, to_byte(alpha), color_blind).to_vector4f();
+    }
+
+    /**
+     * @brief Get a color from the lookup table with given ID.
+     * The ID is automaticall wrapped if greater than `size()`.
+     */
+    template <typename UIntT, std::enable_if_t<std::is_unsigned_v<UIntT>, int> = 0>
+    static Color at(UIntT id, int alpha = 255, bool color_blind = false)
+    {
+        return at(static_cast<std::size_t>(id), alpha, color_blind);
+    }
+    /**
+     * @brief Get a color from the lookup table with given ID.
+     * The ID is automaticall wrapped if greater than `size()`.
+     * If `id` is negative, its absolute value is used.
+     */
+    template <typename IntT, std::enable_if_t<std::is_signed_v<IntT>, int> = 0>
+    static Color at(IntT id, int alpha = 255, bool color_blind = false)
+    {
+        return at(static_cast<std::size_t>(id >= 0 ? id : std::abs(id)), alpha, color_blind);
+    }
+
+    /**
+     * @brief Get a color from the lookup table with given ID (with float values).
+     * The ID is automaticall wrapped if greater than `size()`.
+     */
+    template <typename UIntT, std::enable_if_t<std::is_unsigned_v<UIntT>, int> = 0>
+    static Eigen::Vector4f atf(UIntT id, float alpha = 1.f, bool color_blind = false)
+    {
+        return atf(static_cast<std::size_t>(id), alpha, color_blind);
+    }
+
+    /**
+     * @brief Get a color from the lookup table with given ID (with float values).
+     * The ID is automaticall wrapped if greater than `size()`.
+     * If `id` is negative, its absolute value is used.
+     */
+    template <typename IntT, std::enable_if_t<std::is_signed_v<IntT>, int> = 0>
+    static Eigen::Vector4f atf(IntT id, float alpha = 1.f, bool color_blind = false)
+    {
+        return atf(static_cast<std::size_t>(id >= 0 ? id : std::abs(id)), alpha, color_blind);
+    }
+
+    /// Get the number of colors in the lookup table.;
+    static std::size_t size(bool color_blind = false)
+    {
+        return data(color_blind).size();
+    }
+
+    static std::vector<Color> data(bool color_blind = false)
+    {
+        return color_blind ? KELLY_COLORS_COLOR_BLIND : KELLY_COLORS;
+    }
+};
+
+
+/**
+ * @brief An RGBA color, where each component is a byte in [0, 255]. Additionally contains an id denoting its position
+ */
+struct KellyColor : public Color
+{
+    KellyColor(size_t id = -1) : KellyColor(Color(), id)
+    {
+    }
+
+    KellyColor(uint8_t r, uint8_t g, uint8_t b, size_t id) : Color(r,g,b), id(id)
+    {
+    }
+
+    KellyColor(Color color, size_t id) : KellyColor(color.r, color.g, color.b, id)
+    {
+    }
+
+    bool operator <(const KellyColor &other) const
+    {
+       return id < other.id;
+    }
+
+    size_t id;
+};
+
+/**
+ * @brief Stack of 20 distinguishable colors by Kenneth L. Kelly but without black and white, e.g. usable for creating graphs
+ */
+class KellyColorStack {
+public:
+    /**
+     * @brief Initializes a Stack of colors
+     * @param color_blind 7 instead of 20 colors for visually impaired
+     */
+    KellyColorStack(bool color_blind = false) :
+        colors(createColorStack(KellyLUT::data(color_blind)))
+    {
+    }
+
+    /**
+     * @brief Returns the next Kelly color and removes it from the stack, black color if stack is empty
+     * @return The next color from the top of the stack
+     */
+    KellyColor next()
+    {
+        if (!colors.empty())
+        {
+            auto it = colors.begin();
+            auto color = *it;
+            colors.erase(it);
+            return color;
+        }
+        else return KellyColor();
+    }
+
+    /**
+     * @brief Puts a color back on the stack depending on its id
+     */
+    void putBack(KellyColor color)
+    {
+        colors.insert(color);
+    }
+
+    /**
+     * @return Amount of colors left on the stack
+     */
+    std::size_t left()
+    {
+        return colors.size();
+    }
+
+    bool empty()
+    {
+        return colors.empty();
+    }
+
+private:
+    inline std::set<KellyColor> createColorStack(const std::vector<Color> &colors)
+    {
+        std::set<KellyColor> set;
+        size_t index = 0;
+        for (const Color &color : colors)
+        {
+            set.insert(KellyColor(color, index++));
+        }
+        return set;
+    }
+
+    std::set<KellyColor> colors;
+};
+
+}
diff --git a/SimoxUtility/filesystem.h b/SimoxUtility/filesystem.h
index f2b3aaed65813fe2b2d258f01fc02e7c4f4d3f8e..d0e959b73b4e553aba2dfca9c3cf92b72c2cdacf 100644
--- a/SimoxUtility/filesystem.h
+++ b/SimoxUtility/filesystem.h
@@ -3,4 +3,5 @@
 // This file is generated!
 
 #include "filesystem/list_directory.h"
+#include "filesystem/make_relative.h"
 #include "filesystem/remove_trailing_separator.h"
diff --git a/SimoxUtility/filesystem/make_relative.h b/SimoxUtility/filesystem/make_relative.h
new file mode 100644
index 0000000000000000000000000000000000000000..598dc34b2d9bcaed721baf7ba53288e8c5bdf015
--- /dev/null
+++ b/SimoxUtility/filesystem/make_relative.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <filesystem>
+
+namespace simox::fs
+{
+    //! Return path when appended to a_From will resolve to same as a_To
+    inline std::filesystem::path make_relative(std::filesystem::path a_From, std::filesystem::path a_To)
+    {
+        a_From = std::filesystem::absolute(a_From);
+        a_To = std::filesystem::absolute(a_To);
+        std::filesystem::path ret;
+        std::filesystem::path::const_iterator itrFrom(a_From.begin()), itrTo(a_To.begin());
+        // Find common base
+        for (std::filesystem::path::const_iterator toEnd(a_To.end()), fromEnd(a_From.end()); itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo);
+        // Navigate backwards in directory to reach previously found base
+        for (std::filesystem::path::const_iterator fromEnd(a_From.end()); itrFrom != fromEnd; ++itrFrom)
+        {
+            if ((*itrFrom) != ".")
+                ret /= "..";
+        }
+        // Now navigate down the directory branch
+        //ret.append(itrTo, a_To.end());
+        for (; itrTo != a_To.end(); ++itrTo)
+            ret /= *itrTo;
+        return ret;
+    }
+}
diff --git a/SimoxUtility/rapidxml.h b/SimoxUtility/rapidxml.h
new file mode 100644
index 0000000000000000000000000000000000000000..61180c2ee919dcc628678727b7ab22e95946c7f6
--- /dev/null
+++ b/SimoxUtility/rapidxml.h
@@ -0,0 +1,5 @@
+#pragma once
+
+// This file is generated!
+
+#include "rapidxml/RapidXMLWrapper.h"
diff --git a/SimoxUtility/tests/CMakeLists.txt b/SimoxUtility/tests/CMakeLists.txt
index 81bd1537a5df8485d5f3816ff845d4418cb0bd13..fd1c6cf4ae7e327280d3826ed943696bc085222a 100644
--- a/SimoxUtility/tests/CMakeLists.txt
+++ b/SimoxUtility/tests/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 SET(TEST_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 
 MACRO(ADD_SU_TEST TEST_NAME)
@@ -19,6 +18,7 @@ MACRO(ADD_SU_TEST TEST_NAME)
 
     ADD_EXECUTABLE(${TRG_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.cpp)
     TARGET_LINK_LIBRARIES(${TRG_NAME} PRIVATE SimoxUtility Boost::unit_test_framework)
+    target_include_directories(${TRG_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/..)
     if (NOT Boost_USE_STATIC_LIBS)
         target_compile_definitions(${TRG_NAME} PRIVATE -DBOOST_TEST_DYN_LINK)
     endif ()
diff --git a/SimoxUtility/tests/algorithm/CMakeLists.txt b/SimoxUtility/tests/algorithm/CMakeLists.txt
index c08b9a3bdfb57968c8cfe0b6739ad8fab0701f06..353a58f6ca25f06577d53dd6e9eb5b2cdee533b7 100644
--- a/SimoxUtility/tests/algorithm/CMakeLists.txt
+++ b/SimoxUtility/tests/algorithm/CMakeLists.txt
@@ -1,4 +1,5 @@
 
 ADD_SU_TEST( apply )
 ADD_SU_TEST( for_each_if )
+ADD_SU_TEST( string_tools )
 
diff --git a/SimoxUtility/tests/algorithm/string_tools.cpp b/SimoxUtility/tests/algorithm/string_tools.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a7cfda50d16d2ab2146030579b03225efc13d37
--- /dev/null
+++ b/SimoxUtility/tests/algorithm/string_tools.cpp
@@ -0,0 +1,86 @@
+/**
+* @package    SimoxUtility
+* @author     Andre Meixner
+* @copyright  2020 Andre Meixner
+*/
+
+#define BOOST_TEST_MODULE SimoxUtility/algorithm/string_tools
+
+#include <boost/test/included/unit_test.hpp>
+
+#include <SimoxUtility/algorithm/string.h>
+
+BOOST_AUTO_TEST_CASE(to_lower)
+{
+    BOOST_CHECK_EQUAL(simox::alg::to_lower("TO LoWER tesT!"), "to lower test!");
+}
+
+BOOST_AUTO_TEST_CASE(split)
+{
+    std::string testString = "   test       20 50   30 ";
+    std::string testString2 = "   test   ;   20,50 ; 30 ";
+    std::vector<std::string> expectedResult = { "test", "20", "50", "30" };
+    BOOST_CHECK(simox::alg::split(testString) == expectedResult);
+    BOOST_CHECK(simox::alg::split(testString2, ";,") == expectedResult);
+    BOOST_CHECK_THROW(simox::alg::split_check_size(testString, 3), simox::error::SimoxError);
+}
+
+BOOST_AUTO_TEST_CASE(to_eigen)
+{
+    std::string testString = " 5.0   3   -1.0   ";
+    Eigen::Vector3f expectedResult(5.0, 3.0, -1.0);
+    BOOST_CHECK(simox::alg::to_eigen_vec(testString) == expectedResult);
+    BOOST_CHECK((simox::alg::to_eigen_vec<float, 3>(testString)) == expectedResult);
+    BOOST_CHECK_THROW((simox::alg::to_eigen_vec<float, 4>(testString)), simox::error::SimoxError);
+}
+
+BOOST_AUTO_TEST_CASE(to_string)
+{
+    bool testBool = false;
+    float testFloat = -3.156;
+    double testDouble = -3.34919295196;
+    Eigen::Vector3f testVector3f(5.0, 3.5, -1.0);
+    Eigen::VectorXf testVectorXf(9);
+    testVectorXf << 5.0, 3.5, -1.0, 15, 20, 10, 30, 100, 1;
+    std::vector<float> testVector = {5.0, 3.5, -1.0};
+    std::vector<int> testVectorI = {1, -2, 3};
+    std::vector<std::string> testVectorStr = {"Hello", "World!"};
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testBool), "false");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testFloat), "-3.156");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testDouble), "-3.34919295196");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testVector3f), "5 3.5 -1");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testVectorXf), "5 3.5 -1 15 20 10 30 100 1");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testVector), "5 3.5 -1");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testVectorI, ";"), "1;-2;3");
+    BOOST_CHECK_EQUAL(simox::alg::to_string(testVectorStr), "Hello World!");
+
+}
+
+BOOST_AUTO_TEST_CASE(from_string)
+{
+    std::string testBool = " 0";
+    std::string testBool2 = "FALSE";
+    std::string testFloat = " -3.156";
+    std::string testVector = " 5 3.5 -1.0 ";
+    std::string testVector2 = " 5;3.5;-1.0 ";
+    std::string testVector3 = " 5 ,3.5 ,-1 ,15 ,20, 10,30,100,1 ";
+    bool expectedBool = false;
+    float expectedFloat = -3.156f;
+    Eigen::Vector3f expectedVector3f(5.0, 3.5, -1.0);
+    Eigen::VectorXd expectedVectorXd(9);
+    expectedVectorXd << 5.0, 3.5, -1.0, 15, 20, 10, 30, 100, 1;
+    Eigen::VectorXd expectedVector9d(9);
+    expectedVector9d << 5.0, 3.5, -1.0, 15, 20, 10, 30, 100, 1;
+    std::vector<float> expectedVector = {5.0, 3.5, -1.0};
+    BOOST_CHECK_EQUAL(simox::alg::to_<bool>(testBool), expectedBool);
+    BOOST_CHECK_EQUAL(simox::alg::to_<bool>(testBool2), expectedBool);
+    BOOST_CHECK_EQUAL(simox::alg::to_<float>(testFloat), expectedFloat);
+    BOOST_CHECK(simox::alg::to_vec<float>(testVector) == expectedVector);
+    BOOST_CHECK(simox::alg::to_vec_check_size<float>(testVector2, 3, ";") == expectedVector);
+    BOOST_CHECK((simox::alg::to_eigen_vec<float, 3>(testVector)) == expectedVector3f);
+    BOOST_CHECK(simox::alg::to_eigen_vec(testVector2, ";") == expectedVector3f);
+    BOOST_CHECK(simox::alg::to_eigen_vec<double>(testVector3, ",") == expectedVectorXd);
+    BOOST_CHECK((simox::alg::to_eigen_vec_check_rows<double>(testVector3, 9, ",")) == expectedVectorXd);
+    BOOST_CHECK_THROW((simox::alg::to_eigen_vec_check_rows<double>(testVector3, 10, ",")), simox::error::SimoxError);
+    BOOST_CHECK((simox::alg::to_eigen_vec<double, 9>(testVector3, ",")) == expectedVector9d);
+}
diff --git a/SimoxUtility/tests/filesystem/CMakeLists.txt b/SimoxUtility/tests/filesystem/CMakeLists.txt
index 4d7dc75427dd2bde914e18c9a865f93eafd9dd2c..360ee3a3a3ac7dac8b7130a27deb6aa7ba5c5bfc 100644
--- a/SimoxUtility/tests/filesystem/CMakeLists.txt
+++ b/SimoxUtility/tests/filesystem/CMakeLists.txt
@@ -1,2 +1,3 @@
 
 ADD_SU_TEST( list_directory_test )
+ADD_SU_TEST( make_relative )
diff --git a/SimoxUtility/tests/filesystem/make_relative.cpp b/SimoxUtility/tests/filesystem/make_relative.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9185159721de55d9d3ba9d0702d04b942ab9ac36
--- /dev/null
+++ b/SimoxUtility/tests/filesystem/make_relative.cpp
@@ -0,0 +1,21 @@
+/**
+* @package    VirtualRobot
+* @author     Andre Meixner
+* @copyright  2020 Andre Meixner
+*/
+
+#define BOOST_TEST_MODULE SimoxUtility/filesystem/make_relative
+
+#include <boost/test/included/unit_test.hpp>
+
+#include <SimoxUtility/filesystem/make_relative.h>
+
+namespace fs = simox::fs;
+
+BOOST_AUTO_TEST_CASE(make_relative)
+{
+    BOOST_CHECK_EQUAL(simox::fs::make_relative("a/b/c/e/", "a/b/d/f.xml"), "../../../d/f.xml");
+    auto path = std::filesystem::path("a/b/c/e/g.xml").parent_path();
+    BOOST_CHECK_EQUAL(simox::fs::make_relative(path, "a/b/d/f.xml"), "../../../d/f.xml");
+    BOOST_CHECK_EQUAL(simox::fs::make_relative("a/b", "a/d/f.xml"), "../d/f.xml");
+}
diff --git a/SimoxUtility/xml.h b/SimoxUtility/xml.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f454672c4f8b9ed79e909a3eadf444841604606
--- /dev/null
+++ b/SimoxUtility/xml.h
@@ -0,0 +1,5 @@
+#pragma once
+
+// This file is generated!
+
+#include "xml/rapidxml.h"
diff --git a/SimoxUtility/xml/rapidxml.h b/SimoxUtility/xml/rapidxml.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f5e665bd3bab3091f56bad79ad9c01219956080
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml.h
@@ -0,0 +1,6 @@
+#pragma once
+
+// This file is generated!
+
+#include "rapidxml/RapidXMLForwardDecl.h"
+#include "rapidxml/RapidXMLWrapper.h"
diff --git a/SimoxUtility/xml/rapidxml/RapidXMLForwardDecl.h b/SimoxUtility/xml/rapidxml/RapidXMLForwardDecl.h
new file mode 100644
index 0000000000000000000000000000000000000000..a432705b43add05cffddc01a2f7a873a9f11ee1c
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml/RapidXMLForwardDecl.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <memory>
+#include <filesystem>
+#include "SimoxUtility/error/SimoxError.h"
+
+namespace rapidxml
+{
+    template<class Ch>
+    class xml_node;
+}
+
+namespace simox
+{
+
+namespace error
+{
+    class XMLFormatError : public SimoxError
+    {
+    public:
+        XMLFormatError(const std::string &message = std::string()) : SimoxError(message) {}
+    };
+}
+
+namespace xml
+{
+
+namespace attribute
+{
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    struct XMLAttribute
+    {
+        XMLAttribute(const std::string &attributeName) : attributeName(attributeName)
+        {
+        }
+
+        std::string attributeName;
+    };
+}
+
+class RapidXMLWrapperNode;
+typedef std::shared_ptr<RapidXMLWrapperNode> RapidXMLWrapperNodePtr;
+
+class RapidXMLWrapperRootNode;
+typedef std::shared_ptr<RapidXMLWrapperRootNode> RapidXMLWrapperRootNodePtr;
+
+}
+
+}
diff --git a/SimoxUtility/xml/rapidxml/RapidXMLWrapper.h b/SimoxUtility/xml/rapidxml/RapidXMLWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f37047f967dced8956b5b4a654ce60f46c6fc81
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml/RapidXMLWrapper.h
@@ -0,0 +1,565 @@
+#ifndef __RapidXMLWrapper_H_
+#define __RapidXMLWrapper_H_
+
+#include "rapidxml.hpp"
+#include "rapidxml_print.hpp"
+
+#include "RapidXMLForwardDecl.h"
+
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+#include "SimoxUtility/algorithm/string.h"
+
+namespace simox {
+
+namespace xml {
+
+//! @brief Represents an xml node in the RapidXMLWrapper
+class RapidXMLWrapperNode : public std::enable_shared_from_this<RapidXMLWrapperNode>
+{
+
+    friend class RapidXMLWrapperRootNode;
+
+protected:
+    std::shared_ptr<rapidxml::xml_document<> > doc;
+    rapidxml::xml_node<>* node;
+    RapidXMLWrapperNodePtr parent;
+
+    const char* cloneString(const std::string& str) {
+        return doc->allocate_string(str.c_str());
+    }
+
+    RapidXMLWrapperNode(std::shared_ptr<rapidxml::xml_document<> > doc, rapidxml::xml_node<>* node, RapidXMLWrapperNodePtr parent)
+        : doc(doc), node(node), parent(parent)
+    { }
+
+    RapidXMLWrapperNode(std::shared_ptr<rapidxml::xml_document<> > doc, rapidxml::node_type node_type, RapidXMLWrapperNodePtr parent) : doc(doc), parent(parent) {
+        node = doc->allocate_node(node_type);
+    }
+
+    RapidXMLWrapperNode(std::shared_ptr<rapidxml::xml_document<> > doc, rapidxml::node_type node_type, RapidXMLWrapperNodePtr parent, const std::string& name) : doc(doc), parent(parent) {
+        node = doc->allocate_node(node_type, cloneString(name));
+    }
+
+    void check() const {
+        if (!node) {
+            throw error::XMLFormatError("NullPointerException");
+        }
+    }
+
+    [[noreturn]] inline void throwError(const char* message) {
+        throw error::XMLFormatError("Error at " + getPath() + "! " + message);
+    }
+
+    [[noreturn]] inline void rethrowXMLFormatError() {
+        try
+        {
+            throw;
+        }
+        catch (error::SimoxError &e) {
+            throwError(e.what());
+        }
+        catch (...) {
+            throwError("Unknown Error.");
+        }
+    }
+
+public:
+    static RapidXMLWrapperNodePtr NullNode() {
+        RapidXMLWrapperNodePtr wrapper(new RapidXMLWrapperNode(std::shared_ptr<rapidxml::xml_document<> >(), NULL, nullptr));
+        return wrapper;
+    }
+
+    /**
+        * @brief get_node_ptr only for legacy code.
+        * @return internal pointer
+        */
+    rapidxml::xml_node<>* get_node_ptr() const {
+        return node;
+    }
+
+    /*! Returns the first child node (optional: with the given name).
+        @throws error::XMLFormatError if the node does not exist. */
+    RapidXMLWrapperNodePtr first_node(const char* name = 0) {
+        check();
+
+        rapidxml::xml_node<>* node = this->node->first_node(name, 0, false);
+
+        if (!node) throw error::XMLFormatError(std::string("Node '") + name + "' does not exist in node " + getPath());
+
+        RapidXMLWrapperNodePtr wrapper(new RapidXMLWrapperNode(doc, node, shared_from_this()));
+        return wrapper;
+    }
+
+    /*! Returns the first child node with the given name and attribute. */
+    RapidXMLWrapperNodePtr first_node_with_attribute(const char* name, const std::string &attrName, const std::string &attrValue) {
+        check();
+        std::vector<RapidXMLWrapperNodePtr> n = nodes(name);
+        for (std::vector<RapidXMLWrapperNodePtr>::iterator it; n.begin(), it != n.end(); ++it) {
+            if ((*it)->has_attribute(attrName.c_str()) && (*it)->attribute_value(attrName.c_str()) == attrValue) {
+                return (*it);
+            }
+        }
+        return NullNode();
+    }
+
+    /*! Returns all child nodes (optional: just with the given name). */
+    std::vector<RapidXMLWrapperNodePtr> nodes(const char* name = 0) {
+        std::vector<RapidXMLWrapperNodePtr> vec;
+        nodes(name, vec);
+        return vec;
+    }
+
+    void nodes(const char* name, std::vector<RapidXMLWrapperNodePtr>& vec) {
+        for (RapidXMLWrapperNodePtr n = first_node(name); n->is_valid(); n = n->next_sibling(name)) {
+            vec.push_back(n);
+        }
+    }
+
+    /*! Returns the attribute value.
+        @param attrName The name of the attribute.
+        @throws error::XMLFormatError if the attribute does not exist. */
+    std::string attribute_value(const char* attrName) const {
+        check();
+        rapidxml::xml_attribute<>* attrib = node->first_attribute(attrName, 0, false);
+
+        if (!attrib)
+        {
+            throw error::XMLFormatError(std::string("Attribute '") + attrName + "' does not exist in node " + getPath());
+        }
+
+        return std::string(attrib->value());
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    T attribute_value_(const char* attrName) {
+        try { return alg::to_<T>(attribute_value(attrName)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    template<typename T>
+    T attribute_value_(const attribute::XMLAttribute<T> &attribute) {
+        try { return alg::to_<T>(attribute_value(attribute.attributeName.c_str())); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    std::vector<std::string> attribute_value_vec_str(const char* attrName, const std::string &delimiter = ";") {
+        try { return alg::split(attribute_value(attrName), delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    std::vector<std::string> attribute_value_vec_str(const char* attrName, unsigned int size, const std::string &delimiter = ";") {
+        try { return alg::split_check_size(attribute_value(attrName), size, delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    /*! Checks if a node has a specific attribute.
+        @param attrName The name of the attribute.*/
+    bool has_attribute(const char* attrName) const
+    {
+        check();
+        return node->first_attribute(attrName, 0, false) != 0;
+    }
+
+    /*! Checks if a node has a specific child node.
+        @param attrName The name of the child node.*/
+    bool has_node(const char* nodeName) const
+    {
+        check();
+        return node->first_node(nodeName, 0, false) != 0;
+    }
+
+    /*! Returns the value of an attribute if the attribute exists, otherwise a default value.
+        @param attrName The name of the attribute.
+        @param defaultValue The default value.*/
+    std::string attribute_value_or_default(const char* attrName, const std::string& defaultValue) const
+    {
+        check();
+        rapidxml::xml_attribute<>* attrib = node->first_attribute(attrName, 0, false);
+
+        if (!attrib)
+        {
+            return defaultValue;
+        }
+
+        return std::string(attrib->value());
+    }
+
+    std::vector<std::pair<std::string, std::string> > get_all_attributes()
+    {
+        check();
+        std::vector<std::pair<std::string, std::string> > attributes;
+
+        rapidxml::xml_attribute<>* attrib = node->first_attribute(0, 0, false);
+
+        while (attrib)
+        {
+            std::string name = std::string(attrib->name());
+            std::string value = std::string(attrib->value());
+            std::pair<std::string, std::string> attrPair(name, value);
+            attributes.push_back(attrPair);
+            attrib = attrib->next_attribute();
+        }
+
+        return attributes;
+    }
+
+    /*! Returns the content of an xml node.*/
+    std::string value() const
+    {
+        check();
+        return std::string(node->value());
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    T value_() {
+        try { return alg::to_<T>(value()); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    std::vector<std::string> value_vec_str(const std::string &delimiter = ";") {
+        try { return alg::split(value(), delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    std::vector<std::string> value_vec_str(unsigned int size, const std::string &delimiter = ";") {
+        try { return alg::split_check_size(value(), size, delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    std::vector<T> value_vec_(const std::string &delimiter = "\t ") {
+        try { return alg::to_vec<T>(value(), delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    std::vector<T> value_vec_(unsigned int size, const std::string &delimiter = "\t ") {
+        try { return alg::to_vec<T>(value(), size, delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    Eigen::VectorXf value_eigen_vec(const std::string &delimiter = "\t ") {
+        try { return alg::to_eigen_vec(value(), delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    Eigen::VectorXf value_eigen_vec(unsigned int size, const std::string &delimiter = "\t ") {
+        try { return alg::to_eigen_vec_check_rows<float>(value(), size, delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    Eigen::Vector3f value_eigen_vec3(const std::string &delimiter = "\t ") {
+        try { return alg::to_eigen_vec<float, 3>(value(), delimiter); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    Eigen::Matrix4f value_matrix4f() {
+        Eigen::Matrix4f matrix;
+        for (int i = 1; i <= 4; i++) {
+            std::string row = "row" + simox::alg::to_string(i);
+            simox::xml::RapidXMLWrapperNodePtr rowNode = first_node(row.c_str());
+            for (int j = 1; j <= 4; j++) {
+                std::string column = "c" + simox::alg::to_string(j);
+                matrix(i - 1, j - 1) = rowNode->attribute_value_<float>(column.c_str());
+            }
+        }
+        return matrix;
+    }
+
+    /*! Returns the name of an xml node.*/
+    std::string name() const
+    {
+        check();
+        return std::string(node->name());
+    }
+
+    rapidxml::node_type type()
+    {
+        check();
+        return node->type();
+    }
+
+    std::string first_node_value(const char* nodeName = 0) const
+    {
+        check();
+        rapidxml::xml_node<>* childNode = node->first_node(nodeName, 0, false);
+
+        if (!childNode)
+        {
+            throw error::XMLFormatError(std::string("Node '") + nodeName + "' does not exist in node " + getPath());
+        }
+
+        return std::string(childNode->value());
+    }
+
+    std::string first_node_value_or_default(const char* name, const std::string& defaultValue) const
+    {
+        check();
+        rapidxml::xml_node<>* childNode = node->first_node(name, 0, false);
+
+        if (!childNode)
+        {
+            return defaultValue;
+        }
+
+        return std::string(childNode->value());
+    }
+    RapidXMLWrapperNodePtr next_sibling(const char* name = 0)
+    {
+        check();
+        RapidXMLWrapperNodePtr wrapper(new RapidXMLWrapperNode(doc, node->next_sibling(name, 0, false), shared_from_this()));
+        return wrapper;
+    }
+
+    bool is_valid() const
+    {
+        return node != NULL;
+    }
+
+    std::string getPath() const
+    {
+        check();
+        std::string result = name();
+        rapidxml::xml_node<>* p = node->parent();
+
+        while (p)
+        {
+            result = std::string(p->name()) + "/" + result;
+            p = p->parent();
+        }
+
+        return result;
+    }
+
+    /*! Appends a new attribute to the current node.
+    @return The current Node.*/
+    RapidXMLWrapperNodePtr append_attribute(const std::string& name, const std::string& value) {
+        node->append_attribute(doc->allocate_attribute(cloneString(name), cloneString(value)));
+        return shared_from_this();
+    }
+
+    template<typename T>
+    RapidXMLWrapperNodePtr append_attribute(const attribute::XMLAttribute<T>& attribute, T value) {
+        return append_attribute(attribute.attributeName, alg::to_string(value)); // will not throw error
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    RapidXMLWrapperNodePtr append_attribute(const std::string& name, T value) {
+        try { return append_attribute(name, alg::to_string(value)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    RapidXMLWrapperNodePtr append_attribute(const std::string& name, const std::vector<std::string> value, const std::string &delimiter = ";") {
+        try { return append_attribute(name, alg::to_string(value, delimiter)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    /*! Appends a new node on the current node.
+    @return The new Node.*/
+    RapidXMLWrapperNodePtr append_node(const std::string& name) {
+        RapidXMLWrapperNodePtr node(new RapidXMLWrapperNode(doc, rapidxml::node_element, shared_from_this(), name));
+        this->node->append_node(node->node);
+        return node;
+    }
+
+    /*! Appends a new node on the current node and deletes the first node with the same name
+    @return The new Node.*/
+    RapidXMLWrapperNodePtr append_node_non_duplicate(const std::string& name) {
+        remove_first_node_if_present(name);
+        return append_node(name);
+    }
+
+    /*! Adds std::string content to the current node.
+    @return The current Node.*/
+    RapidXMLWrapperNodePtr append_data_node(const std::string& value) {
+        this->node->append_node(doc->allocate_node(rapidxml::node_data, 0, cloneString(value)));
+        return shared_from_this();
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    RapidXMLWrapperNodePtr append_data_node(T value) {
+        try { return append_data_node(alg::to_string(value)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    template<typename T, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>
+    RapidXMLWrapperNodePtr append_data_node(const std::vector<T> &value, const std::string &delimiter = " ") {
+        try { return append_data_node(alg::to_string(value, delimiter)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    RapidXMLWrapperNodePtr append_data_node(const Eigen::VectorXf value, const std::string &delimiter = " ") {
+        try { return append_data_node(alg::to_string(value, delimiter)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    RapidXMLWrapperNodePtr append_data_node(const std::vector<std::string> value, const std::string &delimiter = ";") {
+        try { return append_data_node(alg::to_string(value, delimiter)); } catch (...) { rethrowXMLFormatError(); };
+    }
+
+    RapidXMLWrapperNodePtr append_data_node(const Eigen::Matrix4f &matrix, const std::string &name) {
+        simox::xml::RapidXMLWrapperNodePtr matrixNode = append_node(name);
+        for (int i = 1; i <= 4; i++) {
+            std::string row = "row" + alg::to_string(i);
+            simox::xml::RapidXMLWrapperNodePtr rowNode = matrixNode->append_node(row);
+            for (int j = 1; j <= 4; j++) {
+                std::string column = "c" + alg::to_string(j);
+                rowNode->append_attribute(column, matrix(i - 1, j - 1));
+            }
+        }
+        return matrixNode;
+    }
+
+    RapidXMLWrapperNodePtr append_string_node(const std::string& name, const std::string& value) {
+        this->node->append_node(doc->allocate_node(rapidxml::node_element, cloneString(name), cloneString(value)));
+        return shared_from_this();
+    }
+
+    void remove_first_node(const std::string &name) {
+        RapidXMLWrapperNodePtr node = first_node(name.c_str());
+        this->node->remove_node(node->node);
+    }
+
+    void remove_first_node_if_present(const std::string &name) {
+        if (has_node(name.c_str())) remove_first_node(name);
+    }
+
+    void remove_attribute(const std::string &name) {
+        this->node->remove_attribute(this->node->first_attribute(name.c_str()));
+    }
+
+    void remove_attribute_if_present(const std::string &name) {
+        if (has_attribute(name.c_str())) remove_attribute(name);
+    }
+
+    /*! Creates an xml std::string representation of this xml nodes' structure
+    @param indent Usage of tabs in the std::string representation for better readability. */
+    std::string print(bool indent = true) {
+        std::string s;
+        rapidxml::print(std::back_inserter(s), *node, indent ? 0 : rapidxml::print_no_indenting);
+        return s;
+    }
+
+    /*! Saves this xml nodes' structure as xml document.
+    @param path Path where the xml document should be saved.
+    @param indent Usage of tabs in the std::string representation for better readability.*/
+    virtual void saveToFile(const std::string& path, bool indent = true) {
+        std::ofstream file;
+        file.open(path.c_str());
+        file << print(indent);
+        file.close();
+    }
+
+    const rapidxml::xml_node<>* getNode() {
+        return node;
+    }
+};
+
+//! @brief Helper class for reading information from an xml format via Rapid XML
+class RapidXMLWrapperRootNode : public RapidXMLWrapperNode
+{
+private:
+    char* cstr; // The string must persist for the lifetime of the document.
+    std::filesystem::path path;
+
+    RapidXMLWrapperRootNode(const std::string& xml, const  std::filesystem::path &path =  std::filesystem::path())
+        : RapidXMLWrapperNode(getDocument(xml), NULL, nullptr), path(path)
+    {
+        node = doc->first_node();
+    }
+
+    RapidXMLWrapperRootNode(std::shared_ptr<rapidxml::xml_document<> > doc, const std::string &name)
+        : RapidXMLWrapperNode(doc, rapidxml::node_element, nullptr, name), path(std::filesystem::path())
+    {
+        cstr = new char[0];
+    }
+
+    std::shared_ptr<rapidxml::xml_document<> > getDocument(const std::string& xml) {
+        if (xml.empty()) throw error::XMLFormatError(std::string("Empty xml!"));
+        cstr = new char[xml.size() + 1];        // Create char buffer to store std::string copy
+        strcpy(cstr, xml.c_str());              // Copy std::string into char buffer
+        try {
+            std::shared_ptr<rapidxml::xml_document<> > doc(new rapidxml::xml_document<>());
+            doc->parse<0>(cstr);                    // Pass the non-const char* to parse()
+            return doc;
+        }
+        catch (rapidxml::parse_error e) {
+            std::string msg = e.what();
+            throw error::XMLFormatError(std::string("No valid xml format! " + msg));
+        }
+    }
+
+public:
+    ~RapidXMLWrapperRootNode() {
+        delete[] cstr;                          // free buffer memory when all is finished
+    }
+
+public:
+    static std::string ReadFileContents(const std::string& path) {
+        try {
+            std::ifstream in(path.c_str());
+
+            if (!in || !in.is_open()) {
+                throw error::XMLFormatError("Could not open XML file " + path);
+            }
+
+            std::stringstream buffer;
+            buffer << in.rdbuf();
+            std::string xmlString(buffer.str());
+            in.close();
+
+            return xmlString;
+        }
+        catch (const std::ifstream::failure& e) {
+            throw error::XMLFormatError("Could not open XML file because " + std::string(e.what()));
+        }
+    }
+
+    /*!
+        Creates a RapidXMLWrapper.
+        @param xml The xml as string.
+        @return The RapidXMLWrapper for the xml string.
+    */
+    static RapidXMLWrapperRootNodePtr FromXmlString(const std::string& xml, const std::string &path = std::string()) {
+        RapidXMLWrapperRootNodePtr wrapper(new RapidXMLWrapperRootNode(xml, path));
+        return wrapper;
+    }
+
+    /*!
+        Creates a RapidXMLWrapper.
+        @param xml Path to an xml document.
+        @return The RapidXMLWrapper for the xml document.
+    */
+    static RapidXMLWrapperRootNodePtr FromFile(const std::string& path) {
+        return FromXmlString(ReadFileContents(path), path);
+    }
+
+    /*! Creates a root node with the given name.
+    @return The root Node. */
+    static RapidXMLWrapperRootNodePtr createRootNode(const std::string& name) {
+        std::shared_ptr<rapidxml::xml_document<> > doc(new rapidxml::xml_document<>());
+        RapidXMLWrapperNodePtr declaration(new RapidXMLWrapperNode(doc, rapidxml::node_declaration, nullptr));
+        declaration->append_attribute("version", "1.0");
+        declaration->append_attribute("encoding", "utf-8");
+        doc->append_node(declaration->node);
+        RapidXMLWrapperRootNodePtr rootNode = RapidXMLWrapperRootNodePtr(new RapidXMLWrapperRootNode(doc, name));
+        doc->append_node(rootNode->node);
+        return rootNode;
+    }
+
+    /*! Saves the created xml structure as xml document.
+    @param path Path where the xml document should be saved.
+    @param indent Usage of tabs in the std::string representation for better readability.*/
+    void saveToFile(const std::string& path, bool indent = true) override {
+        setPath(path);
+        RapidXMLWrapperNode::saveToFile(path, indent);
+    }
+
+    /*! Saves the created xml structure as xml document at the same path it was loaded
+    @param indent Usage of tabs in the std::string representation for better readability.
+    @throws error::XMLFormatError if path value is empty */
+    void saveToFile(bool indent = true) {
+        if (!path.empty()) saveToFile(path, indent);
+        else throw error::XMLFormatError("Empty path variable!");
+    }
+
+    void setPath(const std::string &path) {
+        this->path = path;
+    }
+
+    std::string getPath() {
+        return path;
+    }
+};
+
+}
+}
+
+#endif
diff --git a/SimoxUtility/xml/rapidxml/rapidxml.hpp b/SimoxUtility/xml/rapidxml/rapidxml.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5bc4c0ba537caf44ba65d88e77621425490f4672
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml/rapidxml.hpp
@@ -0,0 +1,2966 @@
+// #pragma once is deliberately not used to make it possible to include both ArmarX and Simox rapidxml
+#ifndef __RAPIDXML_H_INCLUDE__
+#define __RAPIDXML_H_INCLUDE__
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+#include <cstdlib>      // For std::size_t
+#include <cassert>      // For assert
+#include <new>          // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4).
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4127)   // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
+    //! this function is called to notify user about the error.
+    //! It must be defined by the user.
+    //! <br><br>
+    //! This function cannot return. If it does, the results are undefined.
+    //! <br><br>
+    //! A very simple definition might look like that:
+    //! <pre>
+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+    //! {
+    //!     std::cout << "Parse error: " << what << "\n";
+    //!     std::abort();
+    //! }
+    //! </pre>
+    //! \param what Human readable description of the error.
+    //! \param where Pointer to character data where error was detected.
+    void parse_error_handler(const char* what, void* where);
+}
+
+#else
+
+#include <exception>    // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+    //! Parse error exception.
+    //! This exception is thrown by the parser when an error occurs.
+    //! Use what() function to get human-readable error message.
+    //! Use where() function to get a pointer to position within source text where error was detected.
+    //! <br><br>
+    //! If throwing exceptions by the parser is undesirable,
+    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+    //! This function must be defined by the user.
+    //! <br><br>
+    //! This class derives from <code>std::exception</code> class.
+    class parse_error: public std::exception
+    {
+
+    public:
+
+        //! Constructs parse error
+        parse_error(const char* what, void* where)
+            : m_what(what)
+            , m_where(where)
+        {
+        }
+
+        //! Gets human readable description of error.
+        //! \return Pointer to null terminated description of the error.
+        const char* what() const noexcept override
+        {
+            return m_what;
+        }
+
+        //! Gets pointer to character data where error happened.
+        //! Ch should be the same as char type of xml_document that produced the error.
+        //! \return Pointer to location within the parsed string where error occured.
+        template<class Ch>
+        Ch* where() const
+        {
+            return reinterpret_cast<Ch*>(m_where);
+        }
+
+    private:
+
+        const char* m_what;
+        void* m_where;
+
+    };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+// Size of static memory block of memory_pool.
+// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+// No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+// Size of dynamic memory block of memory_pool.
+// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+// Memory allocation alignment.
+// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+// All memory allocations for nodes, attributes and strings will be aligned to this value.
+// This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+#define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+    // Forward declarations
+    template<class Ch> class xml_node;
+    template<class Ch> class xml_attribute;
+    template<class Ch> class xml_document;
+
+    //! Enumeration listing all node types produced by the parser.
+    //! Use xml_node::type() function to query node type.
+    enum node_type
+    {
+        node_document,      //!< A document node. Name and value are empty.
+        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
+        node_data,          //!< A data node. Name is empty. Value contains data text.
+        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
+        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
+        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+        node_pi             //!< A PI node. Name contains target. Value contains instructions.
+    };
+
+    ///////////////////////////////////////////////////////////////////////
+    // Parsing flags
+
+    //! Parse flag instructing the parser to not create data nodes.
+    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_data_nodes = 0x1;
+
+    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+    //! Can be combined with other flags by use of | operator.
+    //! Note that child data nodes of element node take precendence over its value when printing.
+    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_element_values = 0x2;
+
+    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+    //! By default zero terminators are placed, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_string_terminators = 0x4;
+
+    //! Parse flag instructing the parser to not translate entities in the source text.
+    //! By default entities are translated, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_entity_translation = 0x8;
+
+    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+    //! By default, UTF-8 handling is enabled.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_utf8 = 0x10;
+
+    //! Parse flag instructing the parser to create XML declaration node.
+    //! By default, declaration node is not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_declaration_node = 0x20;
+
+    //! Parse flag instructing the parser to create comments nodes.
+    //! By default, comment nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_comment_nodes = 0x40;
+
+    //! Parse flag instructing the parser to create DOCTYPE node.
+    //! By default, doctype node is not created.
+    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_doctype_node = 0x80;
+
+    //! Parse flag instructing the parser to create PI nodes.
+    //! By default, PI nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_pi_nodes = 0x100;
+
+    //! Parse flag instructing the parser to validate closing tag names.
+    //! If not set, name inside closing tag is irrelevant to the parser.
+    //! By default, closing tags are not validated.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_validate_closing_tags = 0x200;
+
+    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+    //! By default, whitespace is not trimmed.
+    //! This flag does not cause the parser to modify source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_trim_whitespace = 0x400;
+
+    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+    //! By default, whitespace is not normalized.
+    //! If this flag is specified, source text will be modified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_normalize_whitespace = 0x800;
+
+    // Compound flags
+
+    //! Parse flags which represent default behaviour of the parser.
+    //! This is always equal to 0, so that all other flags can be simply ored together.
+    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+    //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
+    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+    //! and using the flag will disable it.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_default = 0;
+
+    //! A combination of parse flags that forbids any modifications of the source text.
+    //! This also results in faster parsing. However, note that the following will occur:
+    //! <ul>
+    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+    //! <li>entities will not be translated</li>
+    //! <li>whitespace will not be normalized</li>
+    //! </ul>
+    //! See xml_document::parse() function.
+    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+
+    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+
+    //! A combination of parse flags resulting in largest amount of data being extracted.
+    //! This usually results in slowest parsing.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internals
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Struct that contains lookup tables for the parser
+        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+        template<int Dummy>
+        struct lookup_tables
+        {
+            static const unsigned char lookup_whitespace[256];              // Whitespace table
+            static const unsigned char lookup_node_name[256];               // Node name table
+            static const unsigned char lookup_text[256];                    // Text table
+            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
+            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
+            static const unsigned char lookup_attribute_name[256];          // Attribute name table
+            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
+            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
+            static const unsigned char lookup_digits[256];                  // Digits
+            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
+        };
+
+        // Find length of the string
+        template<class Ch>
+        inline std::size_t measure(const Ch* p)
+        {
+            const Ch* tmp = p;
+
+            while (*tmp)
+            {
+                ++tmp;
+            }
+
+            return tmp - p;
+        }
+
+        // Compare strings for equality
+        template<class Ch>
+        inline bool compare(const Ch* p1, std::size_t size1, const Ch* p2, std::size_t size2, bool case_sensitive)
+        {
+            if (size1 != size2)
+            {
+                return false;
+            }
+
+            if (case_sensitive)
+            {
+                for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (*p1 != *p2)
+                    {
+                        return false;
+                    }
+            }
+            else
+            {
+                for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+                    {
+                        return false;
+                    }
+            }
+
+            return true;
+        }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////
+    // Memory pool
+
+    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+    //! In most cases, you will not need to use this class directly.
+    //! However, if you need to create nodes manually or modify names/values of nodes,
+    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
+    //! Not only is this faster than allocating them by using <code>new</code> operator,
+    //! but also their lifetime will be tied to the lifetime of document,
+    //! possibly simplyfing memory management.
+    //! <br><br>
+    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
+    //! You can also call allocate_string() function to allocate strings.
+    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
+    //! or when the pool is destroyed.
+    //! <br><br>
+    //! It is also possible to create a standalone memory_pool, and use it
+    //! to allocate nodes, whose lifetime will not be tied to any document.
+    //! <br><br>
+    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
+    //! Until static memory is exhausted, no dynamic memory allocations are done.
+    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+    //! by using global <code>new[]</code> and <code>delete[]</code> operators.
+    //! This behaviour can be changed by setting custom allocation routines.
+    //! Use set_allocator() function to set them.
+    //! <br><br>
+    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+    //! This value defaults to the size of pointer on target architecture.
+    //! <br><br>
+    //! To obtain absolutely top performance from the parser,
+    //! it is important that all nodes are allocated from a single, contiguous block of memory.
+    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
+    //! to obtain best wasted memory to performance compromise.
+    //! To do it, define their values before rapidxml.hpp file is included.
+    //! \param Ch Character type of created nodes.
+    template<class Ch = char>
+    class memory_pool
+    {
+
+    public:
+
+        //! \cond internal
+        typedef void* (alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
+        typedef void (free_func)(void*);               // Type of user-defined function used to free memory
+        //! \endcond
+
+        //! Constructs empty pool with default allocator functions.
+        memory_pool()
+            : m_alloc_func(nullptr)
+            , m_free_func(nullptr)
+        {
+            init();
+        }
+
+        //! Destroys pool and frees all the memory.
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Nodes allocated from the pool are no longer valid.
+        ~memory_pool()
+        {
+            clear();
+        }
+
+        //! Allocates a new node from the pool, and optionally assigns name and value to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param type Type of node to create.
+        //! \param name Name to assign to the node, or 0 to assign no name.
+        //! \param value Value to assign to the node, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated node. This pointer will never be NULL.
+        xml_node<Ch>* allocate_node(node_type type,
+                                    const Ch* name = nullptr, const Ch* value = nullptr,
+                                    std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void* memory = allocate_aligned(sizeof(xml_node<Ch>));
+            xml_node<Ch>* node = new(memory) xml_node<Ch>(type);
+
+            if (name)
+            {
+                if (name_size > 0)
+                {
+                    node->name(name, name_size);
+                }
+                else
+                {
+                    node->name(name);
+                }
+            }
+
+            if (value)
+            {
+                if (value_size > 0)
+                {
+                    node->value(value, value_size);
+                }
+                else
+                {
+                    node->value(value);
+                }
+            }
+
+            return node;
+        }
+
+        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param name Name to assign to the attribute, or 0 to assign no name.
+        //! \param value Value to assign to the attribute, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated attribute. This pointer will never be NULL.
+        xml_attribute<Ch>* allocate_attribute(const Ch* name = nullptr, const Ch* value = nullptr,
+                                              std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void* memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+            xml_attribute<Ch>* attribute = new(memory) xml_attribute<Ch>;
+
+            if (name)
+            {
+                if (name_size > 0)
+                {
+                    attribute->name(name, name_size);
+                }
+                else
+                {
+                    attribute->name(name);
+                }
+            }
+
+            if (value)
+            {
+                if (value_size > 0)
+                {
+                    attribute->value(value, value_size);
+                }
+                else
+                {
+                    attribute->value(value);
+                }
+            }
+
+            return attribute;
+        }
+
+        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+        //! \return Pointer to allocated char array. This pointer will never be NULL.
+        Ch* allocate_string(const Ch* source = 0, std::size_t size = 0)
+        {
+            assert(source || size);     // Either source or size (or both) must be specified
+
+            if (size == 0)
+            {
+                size = internal::measure(source) + 1;
+            }
+
+            Ch* result = static_cast<Ch*>(allocate_aligned(size * sizeof(Ch)));
+
+            if (source)
+                for (std::size_t i = 0; i < size; ++i)
+                {
+                    result[i] = source[i];
+                }
+
+            return result;
+        }
+
+        //! Clones an xml_node and its hierarchy of child nodes and attributes.
+        //! Nodes and attributes are allocated from this memory pool.
+        //! Names and values are not cloned, they are shared between the clone and the source.
+        //! Result node can be optionally specified as a second parameter,
+        //! in which case its contents will be replaced with cloned source node.
+        //! This is useful when you want to clone entire document.
+        //! \param source Node to clone.
+        //! \param result Node to put results in, or 0 to automatically allocate result node
+        //! \return Pointer to cloned node. This pointer will never be NULL.
+        xml_node<Ch>* clone_node(const xml_node<Ch>* source, xml_node<Ch>* result = 0)
+        {
+            // Prepare result node
+            if (result)
+            {
+                result->remove_all_attributes();
+                result->remove_all_nodes();
+                result->type(source->type());
+            }
+            else
+            {
+                result = allocate_node(source->type());
+            }
+
+            // Clone name and value
+            result->name(source->name(), source->name_size());
+            result->value(source->value(), source->value_size());
+
+            // Clone child nodes and attributes
+            for (xml_node<Ch>* child = source->first_node(); child; child = child->next_sibling())
+            {
+                result->append_node(clone_node(child));
+            }
+
+            for (xml_attribute<Ch>* attr = source->first_attribute(); attr; attr = attr->next_attribute())
+            {
+                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+            }
+
+            return result;
+        }
+
+        //! Clears the pool.
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Any nodes or strings allocated from the pool will no longer be valid.
+        void clear()
+        {
+            while (m_begin != m_static_memory)
+            {
+                char* previous_begin = reinterpret_cast<header*>(align(m_begin))->previous_begin;
+
+                if (m_free_func)
+                {
+                    m_free_func(m_begin);
+                }
+                else
+                {
+                    delete[] m_begin;
+                }
+
+                m_begin = previous_begin;
+            }
+
+            init();
+        }
+
+        //! Sets or resets the user-defined memory allocation functions for the pool.
+        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+        //! Allocation function must not return invalid pointer on failure. It should either throw,
+        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
+        //! If it returns invalid pointer, results are undefined.
+        //! <br><br>
+        //! User defined allocation functions must have the following forms:
+        //! <br><code>
+        //! <br>void *allocate(std::size_t size);
+        //! <br>void free(void *pointer);
+        //! </code><br>
+        //! \param af Allocation function, or 0 to restore default function
+        //! \param ff Free function, or 0 to restore default function
+        void set_allocator(alloc_func* af, free_func* ff)
+        {
+            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
+            m_alloc_func = af;
+            m_free_func = ff;
+        }
+
+    private:
+
+        struct header
+        {
+            char* previous_begin;
+        };
+
+        void init()
+        {
+            m_begin = m_static_memory;
+            m_ptr = align(m_begin);
+            m_end = m_static_memory + sizeof(m_static_memory);
+        }
+
+        char* align(char* ptr)
+        {
+            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+            return ptr + alignment;
+        }
+
+        char* allocate_raw(std::size_t size)
+        {
+            // Allocate
+            void* memory;
+
+            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
+            {
+                memory = m_alloc_func(size);
+                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+            }
+            else
+            {
+                memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+
+                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+                {
+                    RAPIDXML_PARSE_ERROR("out of memory", 0);
+                }
+
+#endif
+            }
+
+            return static_cast<char*>(memory);
+        }
+
+        void* allocate_aligned(std::size_t size)
+        {
+            // Calculate aligned pointer
+            char* result = align(m_ptr);
+
+            // If not enough memory left in current pool, allocate a new pool
+            if (result + size > m_end)
+            {
+                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+
+                if (pool_size < size)
+                {
+                    pool_size = size;
+                }
+
+                // Allocate
+                std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
+                char* raw_memory = allocate_raw(alloc_size);
+
+                // Setup new pool in allocated memory
+                char* pool = align(raw_memory);
+                header* new_header = reinterpret_cast<header*>(pool);
+                new_header->previous_begin = m_begin;
+                m_begin = raw_memory;
+                m_ptr = pool + sizeof(header);
+                m_end = raw_memory + alloc_size;
+
+                // Calculate aligned pointer again using new pool
+                result = align(m_ptr);
+            }
+
+            // Update pool and return aligned pointer
+            m_ptr = result + size;
+            return result;
+        }
+
+        char* m_begin;                                      // Start of raw memory making up current pool
+        char* m_ptr;                                        // First free byte in current pool
+        char* m_end;                                        // One past last available byte in current pool
+        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
+        alloc_func* m_alloc_func;                           // Allocator function, or 0 if default is to be used
+        free_func* m_free_func;                             // Free function, or 0 if default is to be used
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML base
+
+    //! Base class for xml_node and xml_attribute implementing common functions:
+    //! name(), name_size(), value(), value_size() and parent().
+    //! \param Ch Character type to use
+    template<class Ch = char>
+    class xml_base
+    {
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+
+        // Construct a base with empty name, value and parent
+        xml_base()
+            : m_name(nullptr)
+            , m_value(nullptr)
+            , m_parent(nullptr)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+
+        //! Gets name of the node.
+        //! Interpretation of name depends on type of node.
+        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use name_size() function to determine length of the name.
+        //! \return Name of node, or empty string if node has no name.
+        Ch* name() const
+        {
+            return m_name ? m_name : nullstr();
+        }
+
+        //! Gets size of node name, not including terminator character.
+        //! This function works correctly irrespective of whether name is or is not zero terminated.
+        //! \return Size of node name, in characters.
+        std::size_t name_size() const
+        {
+            return m_name ? m_name_size : 0;
+        }
+
+        //! Gets value of node.
+        //! Interpretation of value depends on type of node.
+        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use value_size() function to determine length of the value.
+        //! \return Value of node, or empty string if node has no value.
+        Ch* value() const
+        {
+            return m_value ? m_value : nullstr();
+        }
+
+        //! Gets size of node value, not including terminator character.
+        //! This function works correctly irrespective of whether value is or is not zero terminated.
+        //! \return Size of node value, in characters.
+        std::size_t value_size() const
+        {
+            return m_value ? m_value_size : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+
+        //! Sets name of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it.
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of name must be specified separately, because name does not have to be zero terminated.
+        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! \param name Name of node to set. Does not have to be zero terminated.
+        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+        void name(const Ch* name, std::size_t size)
+        {
+            m_name = const_cast<Ch*>(name);
+            m_name_size = size;
+        }
+
+        //! Sets name of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+        //! \param name Name of node to set. Must be zero terminated.
+        void name(const Ch* name)
+        {
+            this->name(name, internal::measure(name));
+        }
+
+        //! Sets value of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it.
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of value must be specified separately, because it does not have to be zero terminated.
+        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! <br><br>
+        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+        //! \param value value of node to set. Does not have to be zero terminated.
+        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+        void value(const Ch* value, std::size_t size)
+        {
+            m_value = const_cast<Ch*>(value);
+            m_value_size = size;
+        }
+
+        //! Sets value of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+        //! \param value Vame of node to set. Must be zero terminated.
+        void value(const Ch* value)
+        {
+            this->value(value, internal::measure(value));
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+
+        //! Gets node parent.
+        //! \return Pointer to parent node, or 0 if there is no parent.
+        xml_node<Ch>* parent() const
+        {
+            return m_parent;
+        }
+
+    protected:
+
+        // Return empty string
+        static Ch* nullstr()
+        {
+            static Ch zero = Ch('\0');
+            return &zero;
+        }
+
+        Ch* m_name;                         // Name of node, or 0 if no name
+        Ch* m_value;                        // Value of node, or 0 if no value
+        std::size_t m_name_size;            // Length of node name, or undefined of no name
+        std::size_t m_value_size;           // Length of node value, or undefined if no value
+        xml_node<Ch>* m_parent;             // Pointer to parent node, or 0 if none
+
+    };
+
+    //! Class representing attribute node of XML document.
+    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
+    //! Thus, this text must persist in memory for the lifetime of attribute.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_attribute: public xml_base<Ch>
+    {
+
+        friend class xml_node<Ch>;
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+
+        //! Constructs an empty attribute with the specified type.
+        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+        xml_attribute()
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+
+        //! Gets document of which attribute is a child.
+        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+        xml_document<Ch>* document() const
+        {
+            if (xml_node<Ch>* node = this->parent())
+            {
+                while (node->parent())
+                {
+                    node = node->parent();
+                }
+
+                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+
+        //! Gets previous attribute, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch>* previous_attribute(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_attribute<Ch>* attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                    {
+                        return attribute;
+                    }
+
+                return 0;
+            }
+            else
+            {
+                return this->m_parent ? m_prev_attribute : 0;
+            }
+        }
+
+        //! Gets next attribute, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch>* next_attribute(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_attribute<Ch>* attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                    {
+                        return attribute;
+                    }
+
+                return nullptr;
+            }
+            else
+            {
+                return this->m_parent ? m_next_attribute : nullptr;
+            }
+        }
+
+    private:
+
+        xml_attribute<Ch>* m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+        xml_attribute<Ch>* m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML node
+
+    //! Class representing a node of XML document.
+    //! Each node may have associated name and value strings, which are available through name() and value() functions.
+    //! Interpretation of name and value depends on type of the node.
+    //! Type of node can be determined by using type() function.
+    //! <br><br>
+    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
+    //! Thus, this text must persist in the memory for the lifetime of node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_node: public xml_base<Ch>
+    {
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+
+        //! Constructs an empty node with the specified type.
+        //! Consider using memory_pool of appropriate document to allocate nodes manually.
+        //! \param type Type of node to construct.
+        xml_node(node_type type)
+            : m_type(type)
+            , m_first_node(nullptr)
+            , m_first_attribute(nullptr)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+
+        //! Gets type of node.
+        //! \return Type of node.
+        node_type type() const
+        {
+            return m_type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+
+        //! Gets document of which node is a child.
+        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+        xml_document<Ch>* document() const
+        {
+            xml_node<Ch>* node = const_cast<xml_node<Ch> *>(this);
+
+            while (node->parent())
+            {
+                node = node->parent();
+            }
+
+            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+        }
+
+        //! Gets first child node, optionally matching node name.
+        //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch>* first_node(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_node<Ch>* child = m_first_node; child; child = child->next_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                    {
+                        return child;
+                    }
+
+                return nullptr;
+            }
+            else
+            {
+                return m_first_node;
+            }
+        }
+
+        //! Gets last child node, optionally matching node name.
+        //! Behaviour is undefined if node has no children.
+        //! Use first_node() to test if node has children.
+        //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch>* last_node(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(m_first_node);  // Cannot query for last child if node has no children
+
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_node<Ch>* child = m_last_node; child; child = child->previous_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                    {
+                        return child;
+                    }
+
+                return 0;
+            }
+            else
+            {
+                return m_last_node;
+            }
+        }
+
+        //! Gets previous sibling node, optionally matching node name.
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch>* previous_sibling(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_node<Ch>* sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                    {
+                        return sibling;
+                    }
+
+                return 0;
+            }
+            else
+            {
+                return m_prev_sibling;
+            }
+        }
+
+        //! Gets next sibling node, optionally matching node name.
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch>* next_sibling(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_node<Ch>* sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                    {
+                        return sibling;
+                    }
+
+                return nullptr;
+            }
+            else
+            {
+                return m_next_sibling;
+            }
+        }
+
+        //! Gets first attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch>* first_attribute(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_attribute<Ch>* attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                    {
+                        return attribute;
+                    }
+
+                return nullptr;
+            }
+            else
+            {
+                return m_first_attribute;
+            }
+        }
+
+        //! Gets last attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch>* last_attribute(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                {
+                    name_size = internal::measure(name);
+                }
+
+                for (xml_attribute<Ch>* attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                    {
+                        return attribute;
+                    }
+
+                return 0;
+            }
+            else
+            {
+                return m_first_attribute ? m_last_attribute : 0;
+            }
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+
+        //! Sets type of node.
+        //! \param type Type of node to set.
+        void type(node_type type)
+        {
+            m_type = type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node manipulation
+
+        //! Prepends a new child node.
+        //! The prepended child becomes the first child, and all existing children are moved one position back.
+        //! \param child Node to prepend.
+        void prepend_node(xml_node<Ch>* child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+
+            if (first_node())
+            {
+                child->m_next_sibling = m_first_node;
+                m_first_node->m_prev_sibling = child;
+            }
+            else
+            {
+                child->m_next_sibling = 0;
+                m_last_node = child;
+            }
+
+            m_first_node = child;
+            child->m_parent = this;
+            child->m_prev_sibling = 0;
+        }
+
+        //! Appends a new child node.
+        //! The appended child becomes the last child.
+        //! \param child Node to append.
+        void append_node(xml_node<Ch>* child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+
+            if (first_node())
+            {
+                child->m_prev_sibling = m_last_node;
+                m_last_node->m_next_sibling = child;
+            }
+            else
+            {
+                child->m_prev_sibling = nullptr;
+                m_first_node = child;
+            }
+
+            m_last_node = child;
+            child->m_parent = this;
+            child->m_next_sibling = nullptr;
+        }
+
+        //! Inserts a new child node at specified place inside the node.
+        //! All children after and including the specified node are moved one position back.
+        //! \param where Place where to insert the child, or 0 to insert at the back.
+        //! \param child Node to insert.
+        void insert_node(xml_node<Ch>* where, xml_node<Ch>* child)
+        {
+            assert(!where || where->parent() == this);
+            assert(child && !child->parent() && child->type() != node_document);
+
+            if (where == m_first_node)
+            {
+                prepend_node(child);
+            }
+            else if (where == 0)
+            {
+                append_node(child);
+            }
+            else
+            {
+                child->m_prev_sibling = where->m_prev_sibling;
+                child->m_next_sibling = where;
+                where->m_prev_sibling->m_next_sibling = child;
+                where->m_prev_sibling = child;
+                child->m_parent = this;
+            }
+        }
+
+        //! Removes first child node.
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_first_node()
+        {
+            assert(first_node());
+            xml_node<Ch>* child = m_first_node;
+            m_first_node = child->m_next_sibling;
+
+            if (child->m_next_sibling)
+            {
+                child->m_next_sibling->m_prev_sibling = 0;
+            }
+            else
+            {
+                m_last_node = 0;
+            }
+
+            child->m_parent = 0;
+        }
+
+        //! Removes last child of the node.
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_last_node()
+        {
+            assert(first_node());
+            xml_node<Ch>* child = m_last_node;
+
+            if (child->m_prev_sibling)
+            {
+                m_last_node = child->m_prev_sibling;
+                child->m_prev_sibling->m_next_sibling = 0;
+            }
+            else
+            {
+                m_first_node = 0;
+            }
+
+            child->m_parent = 0;
+        }
+
+        //! Removes specified child from the node
+        // \param where Pointer to child to be removed.
+        void remove_node(xml_node<Ch>* where)
+        {
+            assert(where && where->parent() == this);
+            assert(first_node());
+
+            if (where == m_first_node)
+            {
+                remove_first_node();
+            }
+            else if (where == m_last_node)
+            {
+                remove_last_node();
+            }
+            else
+            {
+                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all child nodes (but not attributes).
+        void remove_all_nodes()
+        {
+            for (xml_node<Ch>* node = first_node(); node; node = node->m_next_sibling)
+            {
+                node->m_parent = nullptr;
+            }
+
+            m_first_node = nullptr;
+        }
+
+        //! Prepends a new attribute to the node.
+        //! \param attribute Attribute to prepend.
+        void prepend_attribute(xml_attribute<Ch>* attribute)
+        {
+            assert(attribute && !attribute->parent());
+
+            if (first_attribute())
+            {
+                attribute->m_next_attribute = m_first_attribute;
+                m_first_attribute->m_prev_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_next_attribute = 0;
+                m_last_attribute = attribute;
+            }
+
+            m_first_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_prev_attribute = 0;
+        }
+
+        //! Appends a new attribute to the node.
+        //! \param attribute Attribute to append.
+        void append_attribute(xml_attribute<Ch>* attribute)
+        {
+            assert(attribute && !attribute->parent());
+
+            if (first_attribute())
+            {
+                attribute->m_prev_attribute = m_last_attribute;
+                m_last_attribute->m_next_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_prev_attribute = nullptr;
+                m_first_attribute = attribute;
+            }
+
+            m_last_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_next_attribute = nullptr;
+        }
+
+        //! Inserts a new attribute at specified place inside the node.
+        //! All attributes after and including the specified attribute are moved one position back.
+        //! \param where Place where to insert the attribute, or 0 to insert at the back.
+        //! \param attribute Attribute to insert.
+        void insert_attribute(xml_attribute<Ch>* where, xml_attribute<Ch>* attribute)
+        {
+            assert(!where || where->parent() == this);
+            assert(attribute && !attribute->parent());
+
+            if (where == m_first_attribute)
+            {
+                prepend_attribute(attribute);
+            }
+            else if (where == 0)
+            {
+                append_attribute(attribute);
+            }
+            else
+            {
+                attribute->m_prev_attribute = where->m_prev_attribute;
+                attribute->m_next_attribute = where;
+                where->m_prev_attribute->m_next_attribute = attribute;
+                where->m_prev_attribute = attribute;
+                attribute->m_parent = this;
+            }
+        }
+
+        //! Removes first attribute of the node.
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_first_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch>* attribute = m_first_attribute;
+
+            if (attribute->m_next_attribute)
+            {
+                attribute->m_next_attribute->m_prev_attribute = 0;
+            }
+            else
+            {
+                m_last_attribute = 0;
+            }
+
+            attribute->m_parent = 0;
+            m_first_attribute = attribute->m_next_attribute;
+        }
+
+        //! Removes last attribute of the node.
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_last_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch>* attribute = m_last_attribute;
+
+            if (attribute->m_prev_attribute)
+            {
+                attribute->m_prev_attribute->m_next_attribute = 0;
+                m_last_attribute = attribute->m_prev_attribute;
+            }
+            else
+            {
+                m_first_attribute = 0;
+            }
+
+            attribute->m_parent = 0;
+        }
+
+        //! Removes specified attribute from node.
+        //! \param where Pointer to attribute to be removed.
+        void remove_attribute(xml_attribute<Ch>* where)
+        {
+            assert(first_attribute() && where->parent() == this);
+
+            if (where == m_first_attribute)
+            {
+                remove_first_attribute();
+            }
+            else if (where == m_last_attribute)
+            {
+                remove_last_attribute();
+            }
+            else
+            {
+                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all attributes of node.
+        void remove_all_attributes()
+        {
+            for (xml_attribute<Ch>* attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+            {
+                attribute->m_parent = nullptr;
+            }
+
+            m_first_attribute = nullptr;
+        }
+
+    private:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Restrictions
+
+        // No copying
+        xml_node(const xml_node&);
+        void operator =(const xml_node&);
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Data members
+
+        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+        // This is required for maximum performance, as it allows the parser to omit initialization of
+        // unneded/redundant values.
+        //
+        // The rules are as follows:
+        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+        node_type m_type;                       // Type of node; always valid
+        xml_node<Ch>* m_first_node;             // Pointer to first child node, or 0 if none; always valid
+        xml_node<Ch>* m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+        xml_attribute<Ch>* m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
+        xml_attribute<Ch>* m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+        xml_node<Ch>* m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+        xml_node<Ch>* m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML document
+
+    //! This class represents root of the DOM hierarchy.
+    //! It is also an xml_node and a memory_pool through public inheritance.
+    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+    //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
+    //! which are inherited from memory_pool.
+    //! To access root node of the document, use the document itself, as if it was an xml_node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+    {
+
+    public:
+
+        //! Constructs empty XML document
+        xml_document()
+            : xml_node<Ch>(node_document)
+        {
+        }
+
+        //! Parses zero-terminated XML string according to given flags.
+        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+        //! The string must persist for the lifetime of the document.
+        //! In case of error, rapidxml::parse_error exception will be thrown.
+        //! <br><br>
+        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+        //! Make sure that data is zero-terminated.
+        //! <br><br>
+        //! Document can be parsed into multiple times.
+        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+        template<int Flags>
+        void parse(Ch* text)
+        {
+            assert(text);
+
+            // Remove current contents
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+
+            // Parse BOM, if any
+            parse_bom<Flags>(text);
+
+            // Parse children
+            while (1)
+            {
+                // Skip whitespace before node
+                skip<whitespace_pred, Flags>(text);
+
+                if (*text == 0)
+                {
+                    break;
+                }
+
+                // Parse and append new child
+                if (*text == Ch('<'))
+                {
+                    ++text;     // Skip '<'
+
+                    if (xml_node<Ch>* node = parse_node<Flags>(text))
+                    {
+                        this->append_node(node);
+                    }
+                }
+                else
+                {
+                    RAPIDXML_PARSE_ERROR("expected <", text);
+                }
+            }
+
+        }
+
+        //! Clears the document by deleting all nodes and clearing the memory pool.
+        //! All nodes owned by document pool are destroyed.
+        void clear()
+        {
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            memory_pool<Ch>::clear();
+        }
+
+    private:
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal character utility functions
+
+        // Detect whitespace character
+        struct whitespace_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect node name character
+        struct node_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute name character
+        struct attribute_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA)
+        struct text_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_no_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_with_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                {
+                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+                }
+
+                if (Quote == Ch('\"'))
+                {
+                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+                }
+
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pure_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                {
+                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+                }
+
+                if (Quote == Ch('\"'))
+                {
+                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+                }
+
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Insert coded character, using UTF8 or 8-bit ASCII
+        template<int Flags>
+        static void insert_coded_character(Ch*& text, unsigned long code)
+        {
+            if (Flags & parse_no_utf8)
+            {
+                // Insert 8-bit ASCII character
+                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+                text[0] = static_cast<unsigned char>(code);
+                text += 1;
+            }
+            else
+            {
+                // Insert UTF8 sequence
+                if (code < 0x80)    // 1 byte sequence
+                {
+                    text[0] = static_cast<unsigned char>(code);
+                    text += 1;
+                }
+                else if (code < 0x800)  // 2 byte sequence
+                {
+                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[0] = static_cast<unsigned char>(code | 0xC0);
+                    text += 2;
+                }
+                else if (code < 0x10000)    // 3 byte sequence
+                {
+                    text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[0] = static_cast<unsigned char>(code | 0xE0);
+                    text += 3;
+                }
+                else if (code < 0x110000)   // 4 byte sequence
+                {
+                    text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
+                    code >>= 6;
+                    text[0] = static_cast<unsigned char>(code | 0xF0);
+                    text += 4;
+                }
+                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+                {
+                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+                }
+            }
+        }
+
+        // Skip characters until predicate evaluates to true
+        template<class StopPred, int Flags>
+        static void skip(Ch*& text)
+        {
+            Ch* tmp = text;
+
+            while (StopPred::test(*tmp))
+            {
+                ++tmp;
+            }
+
+            text = tmp;
+        }
+
+        // Skip characters until predicate evaluates to true while doing the following:
+        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+        // - condensing whitespace sequences to single space character
+        template<class StopPred, class StopPredPure, int Flags>
+        static Ch* skip_and_expand_character_refs(Ch*& text)
+        {
+            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+            if (Flags & parse_no_entity_translation &&
+                !(Flags & parse_normalize_whitespace) &&
+                !(Flags & parse_trim_whitespace))
+            {
+                skip<StopPred, Flags>(text);
+                return text;
+            }
+
+            // Use simple skip until first modification is detected
+            skip<StopPredPure, Flags>(text);
+
+            // Use translation skip
+            Ch* src = text;
+            Ch* dest = src;
+
+            while (StopPred::test(*src))
+            {
+                // If entity translation is enabled
+                if (!(Flags & parse_no_entity_translation))
+                {
+                    // Test if replacement is needed
+                    if (src[0] == Ch('&'))
+                    {
+                        switch (src[1])
+                        {
+
+                            // &amp; &apos;
+                            case Ch('a'):
+                                if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+                                {
+                                    *dest = Ch('&');
+                                    ++dest;
+                                    src += 5;
+                                    continue;
+                                }
+
+                                if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+                                {
+                                    *dest = Ch('\'');
+                                    ++dest;
+                                    src += 6;
+                                    continue;
+                                }
+
+                                break;
+
+                            // &quot;
+                            case Ch('q'):
+                                if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+                                {
+                                    *dest = Ch('"');
+                                    ++dest;
+                                    src += 6;
+                                    continue;
+                                }
+
+                                break;
+
+                            // &gt;
+                            case Ch('g'):
+                                if (src[2] == Ch('t') && src[3] == Ch(';'))
+                                {
+                                    *dest = Ch('>');
+                                    ++dest;
+                                    src += 4;
+                                    continue;
+                                }
+
+                                break;
+
+                            // &lt;
+                            case Ch('l'):
+                                if (src[2] == Ch('t') && src[3] == Ch(';'))
+                                {
+                                    *dest = Ch('<');
+                                    ++dest;
+                                    src += 4;
+                                    continue;
+                                }
+
+                                break;
+
+                            // &#...; - assumes ASCII
+                            case Ch('#'):
+                                if (src[2] == Ch('x'))
+                                {
+                                    unsigned long code = 0;
+                                    src += 3;   // Skip &#x
+
+                                    while (1)
+                                    {
+                                        unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+
+                                        if (digit == 0xFF)
+                                        {
+                                            break;
+                                        }
+
+                                        code = code * 16 + digit;
+                                        ++src;
+                                    }
+
+                                    insert_coded_character<Flags>(dest, code);    // Put character in output
+                                }
+                                else
+                                {
+                                    unsigned long code = 0;
+                                    src += 2;   // Skip &#
+
+                                    while (1)
+                                    {
+                                        unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+
+                                        if (digit == 0xFF)
+                                        {
+                                            break;
+                                        }
+
+                                        code = code * 10 + digit;
+                                        ++src;
+                                    }
+
+                                    insert_coded_character<Flags>(dest, code);    // Put character in output
+                                }
+
+                                if (*src == Ch(';'))
+                                {
+                                    ++src;
+                                }
+                                else
+                                {
+                                    RAPIDXML_PARSE_ERROR("expected ;", src);
+                                }
+
+                                continue;
+
+                            // Something else
+                            default:
+                                // Ignore, just copy '&' verbatim
+                                break;
+
+                        }
+                    }
+                }
+
+                // If whitespace condensing is enabled
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Test if condensing is needed
+                    if (whitespace_pred::test(*src))
+                    {
+                        *dest = Ch(' ');
+                        ++dest;    // Put single space in dest
+                        ++src;                      // Skip first whitespace char
+
+                        // Skip remaining whitespace chars
+                        while (whitespace_pred::test(*src))
+                        {
+                            ++src;
+                        }
+
+                        continue;
+                    }
+                }
+
+                // No replacement, only copy character
+                *dest++ = *src++;
+
+            }
+
+            // Return new end
+            text = src;
+            return dest;
+
+        }
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal parsing functions
+
+        // Parse BOM, if any
+        template<int Flags>
+        void parse_bom(Ch*& text)
+        {
+            // UTF-8?
+            if (static_cast<unsigned char>(text[0]) == 0xEF &&
+                static_cast<unsigned char>(text[1]) == 0xBB &&
+                static_cast<unsigned char>(text[2]) == 0xBF)
+            {
+                text += 3;      // Skup utf-8 bom
+            }
+        }
+
+        // Parse XML declaration (<?xml...)
+        template<int Flags>
+        xml_node<Ch>* parse_xml_declaration(Ch*& text)
+        {
+            // If parsing of declaration is disabled
+            if (!(Flags & parse_declaration_node))
+            {
+                // Skip until end of declaration
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (!text[0])
+                    {
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    }
+
+                    ++text;
+                }
+
+                text += 2;    // Skip '?>'
+                return nullptr;
+            }
+
+            // Create declaration
+            xml_node<Ch>* declaration = this->allocate_node(node_declaration);
+
+            // Skip whitespace before attributes or ?>
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse declaration attributes
+            parse_node_attributes<Flags>(text, declaration);
+
+            // Skip ?>
+            if (text[0] != Ch('?') || text[1] != Ch('>'))
+            {
+                RAPIDXML_PARSE_ERROR("expected ?>", text);
+            }
+
+            text += 2;
+
+            return declaration;
+        }
+
+        // Parse XML comment (<!--...)
+        template<int Flags>
+        xml_node<Ch>* parse_comment(Ch*& text)
+        {
+            // If parsing of comments is disabled
+            if (!(Flags & parse_comment_nodes))
+            {
+                // Skip until end of comment
+                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                    {
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    }
+
+                    ++text;
+                }
+
+                text += 3;     // Skip '-->'
+                return nullptr;      // Do not produce comment node
+            }
+
+            // Remember value start
+            Ch* value = text;
+
+            // Skip until end of comment
+            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                {
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                }
+
+                ++text;
+            }
+
+            // Create comment node
+            xml_node<Ch>* comment = this->allocate_node(node_comment);
+            comment->value(value, text - value);
+
+            // Place zero terminator after comment value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                *text = Ch('\0');
+            }
+
+            text += 3;     // Skip '-->'
+            return comment;
+        }
+
+        // Parse DOCTYPE
+        template<int Flags>
+        xml_node<Ch>* parse_doctype(Ch*& text)
+        {
+            // Remember value start
+            Ch* value = text;
+
+            // Skip to >
+            while (*text != Ch('>'))
+            {
+                // Determine character type
+                switch (*text)
+                {
+
+                    // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+                    // This works for all W3C test files except for 2 most wicked
+                    case Ch('['):
+                    {
+                        ++text;     // Skip '['
+                        int depth = 1;
+
+                        while (depth > 0)
+                        {
+                            switch (*text)
+                            {
+                                case Ch('['):
+                                    ++depth;
+                                    break;
+
+                                case Ch(']'):
+                                    --depth;
+                                    break;
+
+                                case 0:
+                                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                            }
+
+                            ++text;
+                        }
+
+                        break;
+                    }
+
+                    // Error on end of text
+                    case Ch('\0'):
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+                    // Other character, skip it
+                    default:
+                        ++text;
+
+                }
+            }
+
+            // If DOCTYPE nodes enabled
+            if (Flags & parse_doctype_node)
+            {
+                // Create a new doctype node
+                xml_node<Ch>* doctype = this->allocate_node(node_doctype);
+                doctype->value(value, text - value);
+
+                // Place zero terminator after value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    *text = Ch('\0');
+                }
+
+                text += 1;      // skip '>'
+                return doctype;
+            }
+            else
+            {
+                text += 1;      // skip '>'
+                return nullptr;
+            }
+
+        }
+
+        // Parse PI
+        template<int Flags>
+        xml_node<Ch>* parse_pi(Ch*& text)
+        {
+            // If creation of PI nodes is enabled
+            if (Flags & parse_pi_nodes)
+            {
+                // Create pi node
+                xml_node<Ch>* pi = this->allocate_node(node_pi);
+
+                // Extract PI target name
+                Ch* name = text;
+                skip<node_name_pred, Flags>(text);
+
+                if (text == name)
+                {
+                    RAPIDXML_PARSE_ERROR("expected PI target", text);
+                }
+
+                pi->name(name, text - name);
+
+                // Skip whitespace between pi target and pi
+                skip<whitespace_pred, Flags>(text);
+
+                // Remember start of pi
+                Ch* value = text;
+
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                    {
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    }
+
+                    ++text;
+                }
+
+                // Set pi value (verbatim, no entity expansion or whitespace normalization)
+                pi->value(value, text - value);
+
+                // Place zero terminator after name and value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    pi->name()[pi->name_size()] = Ch('\0');
+                    pi->value()[pi->value_size()] = Ch('\0');
+                }
+
+                text += 2;                          // Skip '?>'
+                return pi;
+            }
+            else
+            {
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                    {
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    }
+
+                    ++text;
+                }
+
+                text += 2;    // Skip '?>'
+                return nullptr;
+            }
+        }
+
+        // Parse and append data
+        // Return character that ends data.
+        // This is necessary because this character might have been overwritten by a terminating 0
+        template<int Flags>
+        Ch parse_and_append_data(xml_node<Ch>* node, Ch*& text, Ch* contents_start)
+        {
+            // Backup to contents start if whitespace trimming is disabled
+            if (!(Flags & parse_trim_whitespace))
+            {
+                text = contents_start;
+            }
+
+            // Skip until end of data
+            Ch* value = text, *end;
+
+            if (Flags & parse_normalize_whitespace)
+            {
+                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
+            }
+            else
+            {
+                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+            }
+
+            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+            if (Flags & parse_trim_whitespace)
+            {
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+                    if (*(end - 1) == Ch(' '))
+                    {
+                        --end;
+                    }
+                }
+                else
+                {
+                    // Backup until non-whitespace character is found
+                    while (whitespace_pred::test(*(end - 1)))
+                    {
+                        --end;
+                    }
+                }
+            }
+
+            // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+            // Create new data node
+            if (!(Flags & parse_no_data_nodes))
+            {
+                xml_node<Ch>* data = this->allocate_node(node_data);
+                data->value(value, end - value);
+                node->append_node(data);
+            }
+
+            // Add data to parent node if no data exists yet
+            if (!(Flags & parse_no_element_values))
+                if (*node->value() == Ch('\0'))
+                {
+                    node->value(value, end - value);
+                }
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                Ch ch = *text;
+                *end = Ch('\0');
+                return ch;      // Return character that ends data; this is required because zero terminator overwritten it
+            }
+
+            // Return character that ends data
+            return *text;
+        }
+
+        // Parse CDATA
+        template<int Flags>
+        xml_node<Ch>* parse_cdata(Ch*& text)
+        {
+            // If CDATA is disabled
+            if (Flags & parse_no_data_nodes)
+            {
+                // Skip until end of cdata
+                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                    {
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    }
+
+                    ++text;
+                }
+
+                text += 3;      // Skip ]]>
+                return nullptr;       // Do not produce CDATA node
+            }
+
+            // Skip until end of cdata
+            Ch* value = text;
+
+            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                {
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                }
+
+                ++text;
+            }
+
+            // Create new cdata node
+            xml_node<Ch>* cdata = this->allocate_node(node_cdata);
+            cdata->value(value, text - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                *text = Ch('\0');
+            }
+
+            text += 3;      // Skip ]]>
+            return cdata;
+        }
+
+        // Parse element node
+        template<int Flags>
+        xml_node<Ch>* parse_element(Ch*& text)
+        {
+            // Create element node
+            xml_node<Ch>* element = this->allocate_node(node_element);
+
+            // Extract element name
+            Ch* name = text;
+            skip<node_name_pred, Flags>(text);
+
+            if (text == name)
+            {
+                RAPIDXML_PARSE_ERROR("expected element name", text);
+            }
+
+            element->name(name, text - name);
+
+            // Skip whitespace between element name and attributes or >
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse attributes, if any
+            parse_node_attributes<Flags>(text, element);
+
+            // Determine ending type
+            if (*text == Ch('>'))
+            {
+                ++text;
+                parse_node_contents<Flags>(text, element);
+            }
+            else if (*text == Ch('/'))
+            {
+                ++text;
+
+                if (*text != Ch('>'))
+                {
+                    RAPIDXML_PARSE_ERROR("expected >", text);
+                }
+
+                ++text;
+            }
+            else
+            {
+                RAPIDXML_PARSE_ERROR("expected >", text);
+            }
+
+            // Place zero terminator after name
+            if (!(Flags & parse_no_string_terminators))
+            {
+                element->name()[element->name_size()] = Ch('\0');
+            }
+
+            // Return parsed element
+            return element;
+        }
+
+        // Determine node type, and parse it
+        template<int Flags>
+        xml_node<Ch>* parse_node(Ch*& text)
+        {
+            // Parse proper node type
+            switch (text[0])
+            {
+
+                // <...
+                default:
+                    // Parse and append element node
+                    return parse_element<Flags>(text);
+
+                // <?...
+                case Ch('?'):
+                    ++text;     // Skip ?
+
+                    if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+                        (text[1] == Ch('m') || text[1] == Ch('M')) &&
+                        (text[2] == Ch('l') || text[2] == Ch('L')) &&
+                        whitespace_pred::test(text[3]))
+                    {
+                        // '<?xml ' - xml declaration
+                        text += 4;      // Skip 'xml '
+                        return parse_xml_declaration<Flags>(text);
+                    }
+                    else
+                    {
+                        // Parse PI
+                        return parse_pi<Flags>(text);
+                    }
+
+                // <!...
+                case Ch('!'):
+
+                    // Parse proper subset of <! node
+                    switch (text[1])
+                    {
+
+                        // <!-
+                        case Ch('-'):
+                            if (text[2] == Ch('-'))
+                            {
+                                // '<!--' - xml comment
+                                text += 3;     // Skip '!--'
+                                return parse_comment<Flags>(text);
+                            }
+
+                            break;
+
+                        // <![
+                        case Ch('['):
+                            if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
+                                text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+                            {
+                                // '<![CDATA[' - cdata
+                                text += 8;     // Skip '![CDATA['
+                                return parse_cdata<Flags>(text);
+                            }
+
+                            break;
+
+                        // <!D
+                        case Ch('D'):
+                            if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
+                                text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
+                                whitespace_pred::test(text[8]))
+                            {
+                                // '<!DOCTYPE ' - doctype
+                                text += 9;      // skip '!DOCTYPE '
+                                return parse_doctype<Flags>(text);
+                            }
+
+                    }   // switch
+
+                    // Attempt to skip other, unrecognized node types starting with <!
+                    ++text;     // Skip !
+
+                    while (*text != Ch('>'))
+                    {
+                        if (*text == 0)
+                        {
+                            RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                        }
+
+                        ++text;
+                    }
+
+                    ++text;     // Skip '>'
+                    return nullptr;   // No node recognized
+
+            }
+        }
+
+        // Parse contents of the node - children, data etc.
+        template<int Flags>
+        void parse_node_contents(Ch*& text, xml_node<Ch>* node)
+        {
+            // For all children and text
+            while (1)
+            {
+                // Skip whitespace between > and node contents
+                Ch* contents_start = text;      // Store start of node contents before whitespace is skipped
+                skip<whitespace_pred, Flags>(text);
+                Ch next_char = *text;
+
+                // After data nodes, instead of continuing the loop, control jumps here.
+                // This is because zero termination inside parse_and_append_data() function
+                // would wreak havoc with the above code.
+                // Also, skipping whitespace after data nodes is unnecessary.
+after_data_node:
+
+                // Determine what comes next: node closing, child node, data node, or 0?
+                switch (next_char)
+                {
+
+                    // Node closing or child node
+                    case Ch('<'):
+                        if (text[1] == Ch('/'))
+                        {
+                            // Node closing
+                            text += 2;      // Skip '</'
+
+                            if (Flags & parse_validate_closing_tags)
+                            {
+                                // Skip and validate closing tag name
+                                Ch* closing_name = text;
+                                skip<node_name_pred, Flags>(text);
+
+                                if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+                                {
+                                    RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+                                }
+                            }
+                            else
+                            {
+                                // No validation, just skip name
+                                skip<node_name_pred, Flags>(text);
+                            }
+
+                            // Skip remaining whitespace after node name
+                            skip<whitespace_pred, Flags>(text);
+
+                            if (*text != Ch('>'))
+                            {
+                                RAPIDXML_PARSE_ERROR("expected >", text);
+                            }
+
+                            ++text;     // Skip '>'
+                            return;     // Node closed, finished parsing contents
+                        }
+                        else
+                        {
+                            // Child node
+                            ++text;     // Skip '<'
+
+                            if (xml_node<Ch>* child = parse_node<Flags>(text))
+                            {
+                                node->append_node(child);
+                            }
+                        }
+
+                        break;
+
+                    // End of data - error
+                    case Ch('\0'):
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+                    // Data node
+                    default:
+                        next_char = parse_and_append_data<Flags>(node, text, contents_start);
+                        goto after_data_node;   // Bypass regular processing after data nodes
+
+                }
+            }
+        }
+
+        // Parse XML attributes of the node
+        template<int Flags>
+        void parse_node_attributes(Ch*& text, xml_node<Ch>* node)
+        {
+            // For all attributes
+            while (attribute_name_pred::test(*text))
+            {
+                // Extract attribute name
+                Ch* name = text;
+                ++text;     // Skip first character of attribute name
+                skip<attribute_name_pred, Flags>(text);
+
+                if (text == name)
+                {
+                    RAPIDXML_PARSE_ERROR("expected attribute name", name);
+                }
+
+                // Create new attribute
+                xml_attribute<Ch>* attribute = this->allocate_attribute();
+                attribute->name(name, text - name);
+                node->append_attribute(attribute);
+
+                // Skip whitespace after attribute name
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip =
+                if (*text != Ch('='))
+                {
+                    RAPIDXML_PARSE_ERROR("expected =", text);
+                }
+
+                ++text;
+
+                // Add terminating zero after name
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    attribute->name()[attribute->name_size()] = 0;
+                }
+
+                // Skip whitespace after =
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip quote and remember if it was ' or "
+                Ch quote = *text;
+
+                if (quote != Ch('\'') && quote != Ch('"'))
+                {
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                }
+
+                ++text;
+
+                // Extract attribute value and expand char refs in it
+                Ch* value = text, *end;
+                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
+
+                if (quote == Ch('\''))
+                {
+                    end = skip_and_expand_character_refs < attribute_value_pred < Ch('\'') >, attribute_value_pure_pred < Ch('\'') >, AttFlags > (text);
+                }
+                else
+                {
+                    end = skip_and_expand_character_refs < attribute_value_pred < Ch('"') >, attribute_value_pure_pred < Ch('"') >, AttFlags > (text);
+                }
+
+                // Set attribute value
+                attribute->value(value, end - value);
+
+                // Make sure that end quote is present
+                if (*text != quote)
+                {
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                }
+
+                ++text;     // Skip quote
+
+                // Add terminating zero after value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    attribute->value()[attribute->value_size()] = 0;
+                }
+
+                // Skip whitespace after attribute value
+                skip<whitespace_pred, Flags>(text);
+            }
+        }
+
+    };
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Whitespace (space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
+            1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
+            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
+        };
+
+        // Node name (anything but space \n \r \t / > ? \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) (anything but < \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+        // (anything but < \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+        // (anything but < \0 & space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote (anything but ' \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote that does not require processing (anything but ' \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote (anything but " \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote that does not require processing (anything but " \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+            1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Digits (dec and hex, 255 denotes end of numeric character reference)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
+        {
+            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 1
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 2
+            0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 255, 255, 255, 255, 255, 255, // 3
+            255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 4
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 5
+            255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 6
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 7
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 8
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 9
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // A
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // B
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // C
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // D
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // E
+            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 // F
+        };
+
+        // Upper case conversion
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
+        {
+            // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
+            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
+            16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
+            32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
+            48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
+            64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
+            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
+            96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
+            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, // 7
+            128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 8
+            144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 9
+            160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // A
+            176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // B
+            192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // C
+            208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // D
+            224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // E
+            240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // F
+        };
+    }
+    //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif /*__RAPIDXML_H_INCLUDE__*/
diff --git a/SimoxUtility/xml/rapidxml/rapidxml_license.txt b/SimoxUtility/xml/rapidxml/rapidxml_license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3ab806d0af7905bec5932fe0d0a6b253f5951204
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml/rapidxml_license.txt
@@ -0,0 +1,52 @@
+Use of this software is granted under one of the following two licenses,
+to be chosen freely by the user.
+
+1. Boost Software License - Version 1.0 - August 17th, 2003
+===============================================================================
+
+Copyright (c) 2006, 2007 Marcin Kalicinski
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+2. The MIT License
+===============================================================================
+
+Copyright (c) 2006, 2007 Marcin Kalicinski
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal 
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do so, 
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
+IN THE SOFTWARE.
\ No newline at end of file
diff --git a/SimoxUtility/xml/rapidxml/rapidxml_print.hpp b/SimoxUtility/xml/rapidxml/rapidxml_print.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ceed57fac67dab7583d00c3bfe4b73f94423ccd4
--- /dev/null
+++ b/SimoxUtility/xml/rapidxml/rapidxml_print.hpp
@@ -0,0 +1,539 @@
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+#pragma once
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+#include <ostream>
+#include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+    ///////////////////////////////////////////////////////////////////////
+    // Printing flags
+
+    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internal
+
+    //! \cond internal
+    namespace internal
+    {
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Internal character operations
+
+        // Copy characters from given range to given output iterator
+        template<class OutIt, class Ch>
+        inline OutIt copy_chars(const Ch* begin, const Ch* end, OutIt out)
+        {
+            while (begin != end)
+            {
+                *out++ = *begin++;
+            }
+
+            return out;
+        }
+
+        // Copy characters from given range to given output iterator and expand
+        // characters into references (&lt; &gt; &apos; &quot; &amp;)
+        template<class OutIt, class Ch>
+        inline OutIt copy_and_expand_chars(const Ch* begin, const Ch* end, Ch noexpand, OutIt out)
+        {
+            while (begin != end)
+            {
+                if (*begin == noexpand)
+                {
+                    *out++ = *begin;    // No expansion, copy character
+                }
+                else
+                {
+                    switch (*begin)
+                    {
+                        case Ch('<'):
+                            *out++ = Ch('&');
+                            *out++ = Ch('l');
+                            *out++ = Ch('t');
+                            *out++ = Ch(';');
+                            break;
+
+                        case Ch('>'):
+                            *out++ = Ch('&');
+                            *out++ = Ch('g');
+                            *out++ = Ch('t');
+                            *out++ = Ch(';');
+                            break;
+
+                        case Ch('\''):
+                            *out++ = Ch('&');
+                            *out++ = Ch('a');
+                            *out++ = Ch('p');
+                            *out++ = Ch('o');
+                            *out++ = Ch('s');
+                            *out++ = Ch(';');
+                            break;
+
+                        case Ch('"'):
+                            *out++ = Ch('&');
+                            *out++ = Ch('q');
+                            *out++ = Ch('u');
+                            *out++ = Ch('o');
+                            *out++ = Ch('t');
+                            *out++ = Ch(';');
+                            break;
+
+                        case Ch('&'):
+                            *out++ = Ch('&');
+                            *out++ = Ch('a');
+                            *out++ = Ch('m');
+                            *out++ = Ch('p');
+                            *out++ = Ch(';');
+                            break;
+
+                        default:
+                            *out++ = *begin;    // No expansion, copy character
+                    }
+                }
+
+                ++begin;    // Step to next character
+            }
+
+            return out;
+        }
+
+        // Fill given output iterator with repetitions of the same character
+        template<class OutIt, class Ch>
+        inline OutIt fill_chars(OutIt out, int n, Ch ch)
+        {
+            for (int i = 0; i < n; ++i)
+            {
+                *out++ = ch;
+            }
+
+            return out;
+        }
+
+        // Find character
+        template<class Ch, Ch ch>
+        inline bool find_char(const Ch* begin, const Ch* end)
+        {
+            while (begin != end)
+                if (*begin++ == ch)
+                {
+                    return true;
+                }
+
+            return false;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Internal printing operations
+
+        /// Forward declarations
+
+        template<class OutIt, class Ch>
+        OutIt print_children(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_element_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_attributes(OutIt out, const xml_node<Ch>* node, int flags);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_data_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_comment_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        template<class OutIt, class Ch>
+        inline OutIt print_pi_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
+
+        // Print node
+        template<class OutIt, class Ch>
+        inline OutIt print_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            // Print proper node type
+            switch (node->type())
+            {
+
+                // Document
+                case node_document:
+                    out = print_children(out, node, flags, indent);
+                    break;
+
+                // Element
+                case node_element:
+                    out = print_element_node(out, node, flags, indent);
+                    break;
+
+                // Data
+                case node_data:
+                    out = print_data_node(out, node, flags, indent);
+                    break;
+
+                // CDATA
+                case node_cdata:
+                    out = print_cdata_node(out, node, flags, indent);
+                    break;
+
+                // Declaration
+                case node_declaration:
+                    out = print_declaration_node(out, node, flags, indent);
+                    break;
+
+                // Comment
+                case node_comment:
+                    out = print_comment_node(out, node, flags, indent);
+                    break;
+
+                // Doctype
+                case node_doctype:
+                    out = print_doctype_node(out, node, flags, indent);
+                    break;
+
+                // Pi
+                case node_pi:
+                    out = print_pi_node(out, node, flags, indent);
+                    break;
+
+                // Unknown
+                default:
+                    assert(0);
+                    break;
+            }
+
+            // If indenting not disabled, add line break after node
+            if (!(flags & print_no_indenting))
+            {
+                *out = Ch('\n'), ++out;
+            }
+
+            // Return modified iterator
+            return out;
+        }
+
+        // Print children of the node
+        template<class OutIt, class Ch>
+        inline OutIt print_children(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            for (xml_node<Ch>* child = node->first_node(); child; child = child->next_sibling())
+            {
+                out = print_node(out, child, flags, indent);
+            }
+
+            return out;
+        }
+
+        // Print attributes of the node
+        template<class OutIt, class Ch>
+        inline OutIt print_attributes(OutIt out, const xml_node<Ch>* node, int flags)
+        {
+            for (xml_attribute<Ch>* attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+            {
+                if (attribute->name() && attribute->value())
+                {
+                    // Print attribute name
+                    *out = Ch(' '), ++out;
+                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+                    *out = Ch('='), ++out;
+
+                    // Print attribute value using appropriate quote type
+                    if (find_char < Ch, Ch('"') > (attribute->value(), attribute->value() + attribute->value_size()))
+                    {
+                        *out = Ch('\''), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+                        *out = Ch('\''), ++out;
+                    }
+                    else
+                    {
+                        *out = Ch('"'), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+                        *out = Ch('"'), ++out;
+                    }
+                }
+            }
+
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_data_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_data);
+
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_cdata);
+
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<');
+            ++out;
+            *out = Ch('!');
+            ++out;
+            *out = Ch('[');
+            ++out;
+            *out = Ch('C');
+            ++out;
+            *out = Ch('D');
+            ++out;
+            *out = Ch('A');
+            ++out;
+            *out = Ch('T');
+            ++out;
+            *out = Ch('A');
+            ++out;
+            *out = Ch('[');
+            ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch(']');
+            ++out;
+            *out = Ch(']');
+            ++out;
+            *out = Ch('>');
+            ++out;
+            return out;
+        }
+
+        // Print element node
+        template<class OutIt, class Ch>
+        inline OutIt print_element_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_element);
+
+            // Print element name and attributes, if any
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            out = print_attributes(out, node, flags);
+
+            // If node is childless
+            if (node->value_size() == 0 && !node->first_node())
+            {
+                // Print childless node tag ending
+                *out = Ch('/'), ++out;
+                *out = Ch('>'), ++out;
+            }
+            else
+            {
+                // Print normal node tag ending
+                *out = Ch('>'), ++out;
+
+                // Test if node contains a single data node only (and no other nodes)
+                xml_node<Ch>* child = node->first_node();
+
+                if (!child)
+                {
+                    // If node has no children, only print its value without indenting
+                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+                }
+                else if (child->next_sibling() == nullptr && child->type() == node_data)
+                {
+                    // If node has a sole data child, only print its value without indenting
+                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+                }
+                else
+                {
+                    // Print all children with full indenting
+                    if (!(flags & print_no_indenting))
+                    {
+                        *out = Ch('\n'), ++out;
+                    }
+
+                    out = print_children(out, node, flags, indent + 1);
+
+                    if (!(flags & print_no_indenting))
+                    {
+                        out = fill_chars(out, indent, Ch('\t'));
+                    }
+                }
+
+                // Print node end
+                *out = Ch('<'), ++out;
+                *out = Ch('/'), ++out;
+                out = copy_chars(node->name(), node->name() + node->name_size(), out);
+                *out = Ch('>'), ++out;
+            }
+
+            return out;
+        }
+
+        // Print declaration node
+        template<class OutIt, class Ch>
+        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            // Print declaration start
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            *out = Ch('x'), ++out;
+            *out = Ch('m'), ++out;
+            *out = Ch('l'), ++out;
+
+            // Print attributes
+            out = print_attributes(out, node, flags);
+
+            // Print declaration end
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+
+            return out;
+        }
+
+        // Print comment node
+        template<class OutIt, class Ch>
+        inline OutIt print_comment_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_comment);
+
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print doctype node
+        template<class OutIt, class Ch>
+        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_doctype);
+
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('D'), ++out;
+            *out = Ch('O'), ++out;
+            *out = Ch('C'), ++out;
+            *out = Ch('T'), ++out;
+            *out = Ch('Y'), ++out;
+            *out = Ch('P'), ++out;
+            *out = Ch('E'), ++out;
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print pi node
+        template<class OutIt, class Ch>
+        inline OutIt print_pi_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
+        {
+            assert(node->type() == node_pi);
+
+            if (!(flags & print_no_indenting))
+            {
+                out = fill_chars(out, indent, Ch('\t'));
+            }
+
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Printing
+
+    //! Prints XML to given output iterator.
+    //! \param out Output iterator to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output iterator pointing to position immediately after last character of printed text.
+    template<class OutIt, class Ch>
+    inline OutIt print(OutIt out, const xml_node<Ch>& node, int flags = 0)
+    {
+        return internal::print_node(out, &node, flags, 0);
+    }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+    //! Prints XML to given output stream.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output stream.
+    template<class Ch>
+    inline std::basic_ostream<Ch>& print(std::basic_ostream<Ch>& out, const xml_node<Ch>& node, int flags = 0)
+    {
+        print(std::ostream_iterator<Ch>(out), node, flags);
+        return out;
+    }
+
+    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed.
+    //! \return Output stream.
+    template<class Ch>
+    inline std::basic_ostream<Ch>& operator <<(std::basic_ostream<Ch>& out, const xml_node<Ch>& node)
+    {
+        return print(out, node);
+    }
+
+#endif
+
+}
+#endif
diff --git a/VirtualRobot/CMakeLists.txt b/VirtualRobot/CMakeLists.txt
index 84e33388b047a70b8376640a4f6326fdc2c50a13..8e32dec13dc8bb6efd2e7dc038b346604599853c 100644
--- a/VirtualRobot/CMakeLists.txt
+++ b/VirtualRobot/CMakeLists.txt
@@ -217,6 +217,7 @@ SET(SOURCES
     IK/PoseQualityExtendedManipulability.cpp
     IK/PoseQualityManipulability.cpp
     IK/PoseQualityMeasurement.cpp
+    IK/RobotPoseDifferentialIK.cpp
     IK/StackedIK.cpp
     IK/SupportPolygon.cpp
     IK/constraints/BalanceConstraint.cpp
@@ -418,6 +419,7 @@ SET(INCLUDES
     IK/PoseQualityExtendedManipulability.h
     IK/PoseQualityManipulability.h
     IK/PoseQualityMeasurement.h
+    IK/RobotPoseDifferentialIK.h
     IK/StackedIK.h
     IK/SupportPolygon.h
     IK/constraints/BalanceConstraint.h
diff --git a/VirtualRobot/IK/RobotPoseDifferentialIK.cpp b/VirtualRobot/IK/RobotPoseDifferentialIK.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..62ea677fa060538fb70e60dec9a6c2bd384fa391
--- /dev/null
+++ b/VirtualRobot/IK/RobotPoseDifferentialIK.cpp
@@ -0,0 +1,554 @@
+#include "RobotPoseDifferentialIK.h"
+
+#include <Eigen/QR>
+#include <Eigen/Geometry>
+#include <boost/format.hpp>
+#include <boost/bind.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <VirtualRobot/VirtualRobotCommon.h>
+
+#include <algorithm>
+#include <cfloat>
+
+using namespace std;
+
+namespace VirtualRobot {
+
+    RobotPoseDifferentialIK::RobotPoseDifferentialIK(RobotPtr robot, RobotNodeSetPtr _rns, RobotNodePtr _coordSystem, JacobiProvider::InverseJacobiMethod invJacMethod) :
+        DifferentialIK(_rns, _coordSystem, invJacMethod)
+    {
+        this->robot = robot;
+        checkImprovement = true;
+        considerBoxConstraints = true;
+        // saving joint limits
+        _uLimits.resize(rns->getSize());
+        _lLimits.resize(rns->getSize());
+        for (unsigned int i=0; i<rns->getSize(); i++) {
+            RobotNodePtr n = rns->getNode(i);
+            _lLimits[i] = n->getJointLimitLow();
+            _uLimits[i] = n->getJointLimitHigh();
+        }
+    }
+
+
+    Eigen::MatrixXf RobotPoseDifferentialIK::getJacobianMatrix()
+    {
+        if (nRows == 0)
+            this->setNRows();
+        size_t nDoF = nodes.size();
+
+        nDoF += 6; // add 6 DoF for robot pose
+
+        Eigen::MatrixXf Jacobian = Eigen::MatrixXf::Constant(nRows, nDoF,0.0f);
+
+        size_t index = 0;
+        for (size_t i = 0; i < tcp_set.size(); i++)
+        {
+            SceneObjectPtr tcp = tcp_set[i];
+            if (this->targets.find(tcp) != this->targets.end())
+            {
+                IKSolver::CartesianSelection mode = this->modes[tcp];
+                Eigen::MatrixXf partJacobian = this->getJacobianMatrix(tcp, mode);
+                this->localJacobians[i] = partJacobian;
+
+                Jacobian.block(index, 0, partJacobian.rows(), nDoF) = partJacobian.block(0, 0, partJacobian.rows(), nDoF);
+                if (mode & IKSolver::X)
+                    index++;
+                if (mode & IKSolver::Y)
+                    index++;
+                if (mode & IKSolver::Z)
+                    index++;
+                if (mode & IKSolver::Orientation)
+                    index += 3;
+            }
+            else
+                    VR_ERROR << "Internal error?!" << endl; // Error
+        }
+        return Jacobian;
+    }
+
+
+    Eigen::MatrixXf RobotPoseDifferentialIK::getJacobianMatrix(SceneObjectPtr tcp, IKSolver::CartesianSelection mode)
+    {
+        // Get number of degrees of freedom
+        size_t nDoF = nodes.size();
+
+        // using robot position and rotation as dof
+        nDoF += 6;
+
+        // obtain the size of the matrix.
+        unsigned int size = 0;
+        if (mode & IKSolver::X) size++;
+        if (mode & IKSolver::Y) size++;
+        if (mode & IKSolver::Z) size++;
+        if (mode & IKSolver::Orientation) size += 3;
+
+        Eigen::MatrixXf jacJoints = DifferentialIK::getJacobianMatrix(tcp, mode);
+        Eigen::MatrixXf jacRobot(size, 6);
+
+        Eigen::MatrixXf positionRobot = Eigen::MatrixXf::Zero(3, 6);
+        Eigen::MatrixXf orientationRobot = Eigen::MatrixXf::Zero(3, 6);
+        // Add DoF related to robot pose
+        for (size_t i = 0; i < 6; i++)
+        {
+
+            // robot pose
+            if (i < 3)
+            {
+                // pos
+
+                Eigen::Vector3f axis;
+                if (i == 0)
+                    axis = Eigen::Vector3f::UnitX();
+                else if (i == 1)
+                    axis = Eigen::Vector3f::UnitY();
+                else if (i == 2)
+                    axis = Eigen::Vector3f::UnitZ();
+                else
+                {
+                    cout << "int. err. " << endl;
+                    continue;
+                }
+
+                if (coordSystem)
+                {
+                    // convert Vector to local coord system
+                    Eigen::Vector4f result4f = Eigen::Vector4f::Zero();
+                    result4f.segment(0, 3) = axis;
+                    result4f = coordSystem->getGlobalPose().inverse() * result4f;
+                    axis = result4f.head(3);
+                }
+                // if necessary calculate the position part of the Jacobian
+                if (mode & IKSolver::Position)
+                    positionRobot.block(0, i, 3, 1) = axis;
+                // no orientation part required with prismatic joints
+            }
+            else
+            {
+                // ori
+
+                Eigen::Vector3f axis;
+                if (i == 3)
+                    axis = Eigen::Vector3f::UnitX();
+                else if (i == 4)
+                    axis = Eigen::Vector3f::UnitY();
+                else if (i == 5)
+                    axis = Eigen::Vector3f::UnitZ();
+                else
+                {
+                    cout << "int. err. " << endl;
+                    continue;
+                }
+                if (coordSystem)
+                {
+                    // convert Vector to local coord system
+                    Eigen::Vector4f result4f = Eigen::Vector4f::Zero();
+                    result4f.segment(0, 3) = axis;
+                    result4f = coordSystem->getGlobalPose().inverse() * result4f;
+                    axis = result4f.head(3);
+                }
+                // if necessary calculate the position part of the Jacobian
+                if (mode & IKSolver::Position)
+                {
+                    Eigen::Vector3f toTCP;
+                    if (coordSystem)
+                    {
+                        toTCP = coordSystem->toLocalCoordinateSystem(tcp->getGlobalPose()).block(0, 3, 3, 1)
+                            - coordSystem->toLocalCoordinateSystem(robot->getGlobalPose()).block(0, 3, 3, 1);
+                    }
+                    else
+                    {
+                        toTCP = tcp->getGlobalPose().block(0, 3, 3, 1)
+                            - robot->getGlobalPose().block(0, 3, 3, 1);
+                    }
+                    if (convertMMtoM)
+                        toTCP /= 1000.0f;
+                    /*cout << "toTCP: " << tcp->getName() << endl;
+                    cout << axis << endl;
+                    cout << toTCP << endl;*/
+                    Eigen::Vector3f r = axis.cross(toTCP);
+                    //cout << r << endl;
+                    positionRobot.block(0, i, 3, 1) = r;
+                    if (r.norm() > 1e10)
+                    {
+                        cout << "posRobot error" << endl;
+                    }
+                }
+                // and the orientation part
+                if (mode & IKSolver::Orientation)
+                    orientationRobot.block(0, i, 3, 1) = axis;
+            }
+        }
+
+        Eigen::MatrixXf result(size, nDoF);
+        result.block(0, 0, size, nDoF - 6) = jacJoints;
+
+        // copy only what is required (and was previously calculated)
+        unsigned int index = 0;
+        if (mode & IKSolver::X)
+        {
+            result.block(index, nDoF - 6, 1, 6) = positionRobot.row(0);
+            //result.block(0, nDoF - 6 + index, size, 1) = positionRobot.col(0);
+            index++;
+        }
+        if (mode & IKSolver::Y)
+        {
+            result.block(index, nDoF - 6, 1, 6) = positionRobot.row(1);
+            index++;
+        }
+        if (mode & IKSolver::Z)
+        {
+            result.block(index, nDoF - 6, 1, 6) = positionRobot.row(2);
+            index++;
+        }
+        if (mode & IKSolver::Orientation)
+        {
+            result.block(index, nDoF - 6, 3, 6) = orientationRobot;
+        }
+        return result;
+    }
+
+    Eigen::MatrixXd RobotPoseDifferentialIK::computePseudoInverseJacobianMatrixDampedD(const Eigen::MatrixXd &m)
+    {
+        Eigen::JacobiSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
+        Eigen::MatrixXd U = svd.matrixU();
+        Eigen::MatrixXd V = svd.matrixV();
+        Eigen::VectorXd sv = svd.singularValues();
+
+        //float lambda = 1.0f;
+
+        double epsilon = std::numeric_limits<double>::epsilon();
+        double tol = epsilon*std::max(m.rows(),m.cols())*m.norm();
+        //tol = 0.001;
+        //MMM_INFO << "tol" <<  tol << endl;
+        for (int i = 0; i<sv.rows(); i++)
+        {
+            if (sv(i)>tol)
+            sv(i) = 1.0f/ sv(i) ;
+//            sv(i) = sv(i) / (sv(i)*sv(i) + lambda*lambda);
+            else
+                sv(i) = 0.0f;
+        }
+
+        /*if (sv(i) > tol)
+        sv(i) = 1.0f / sv(i);
+        else sv(i) = 0;*/
+
+        return (V*sv.asDiagonal()*U.transpose());
+    }
+
+
+    Eigen::VectorXf RobotPoseDifferentialIK::computeStep(float stepSize)
+    {
+        const bool considerMaxAngle = true;
+
+        if (nRows == 0) this->setNRows();
+        size_t nDoF = nodes.size();
+
+        // consider robot pose as 6d vector
+        nDoF += 6;
+        //this->inverseMethod = DifferentialIK::eSVDDamped;
+        bool jVerbose = verbose;
+        jVerbose = false;
+
+        // init
+        bool bAbort = false;
+        Eigen::VectorXf thetaOld(nDoF);
+        Eigen::VectorXf theta(nDoF);
+        Eigen::VectorXf blockedJointDeltas(nDoF);
+        Eigen::VectorXf blockedJointValues(nDoF);
+        bool bViolation;
+        std::vector<int> blockedJoints;
+        Eigen::VectorXf dTheta(nDoF);
+        //Eigen::MatrixXf pseudo;
+        float maximal = float(10 * M_PI /180.0);
+        float scale;
+        Eigen::VectorXf error;
+        Eigen::VectorXf angularDiff(nDoF-3);
+        Eigen::MatrixXf Jacobian;
+        float maxAngularDifference;// , maxAngularDifference1, maxAngularDifference2;
+
+
+
+        if (considerBoxConstraints)
+        {
+
+            // get joint positions
+            rns->getJointValues(thetaOld);
+            blockedJointValues = thetaOld;
+            blockedJointDeltas.setZero();
+            // main loop
+            int counter = 0;
+            while (!bAbort && counter < 30) {
+                counter++;
+                scale = 1.0;
+                error = getError(stepSize);
+                Jacobian = getJacobianMatrix();
+
+                int rows = Jacobian.rows();
+                for (int blockedJoint : blockedJoints) {
+                    Jacobian.block(0, blockedJoint, rows, 1).setZero();
+                }
+
+
+
+                /*
+                  MatrixXd JacobianXd = Jacobian.cast<double>();
+                  MatrixXd test = Jacobian.transpose().cast<double>()*Jacobian.cast<double>();
+                  FullPivLU<MatrixXd> lu_decomp(test);
+                  cout << "The rank of A is " << lu_decomp.rank() << " (" << test.rows() << "x" << test.cols() << ")" << endl;
+                  */
+
+                Eigen::MatrixXf pseudoXf = computePseudoInverseJacobianMatrix(Jacobian);
+                Eigen::VectorXf dThetaXf = pseudoXf * error;
+                //            Eigen::VectorXf errorXf = Jacobian * dThetaXf;
+                //            MMM_INFO << error.norm() << ", " << errorXf.norm() << endl;
+                dTheta = dThetaXf;
+
+                /*
+                MatrixXd pseudoXd = computePseudoInverseJacobianMatrixDampedD(JacobianXd);
+                VectorXd dThetaXd = pseudoXd * error.cast<double>();
+                dTheta = dThetaXd.cast<float>();
+                Eigen::VectorXd errorXd = JacobianXd * dThetaXd;
+                */
+
+
+                /* Debug Stuff */
+                //            MMM_INFO << error.norm() << ", " << errorXd.norm() << endl;
+                //MMM_INFO << dThetaXd.transpose() << endl << dThetaXf.transpose() << endl;
+
+
+                //cout << "error:" << error << endl;
+                //cout << "THETA:" << dTheta << endl;
+                if (considerMaxAngle)
+                {
+                    scale = 1.0f;
+                    angularDiff.block(0, 0, nDoF - 6, 1) = dTheta.head(nDoF - 6);
+                    angularDiff.block(nDoF - 6, 0, 3, 1) = dTheta.tail(3);
+                    //cout << "angularDiff:" << angularDiff << endl;
+                    maxAngularDifference = angularDiff.array().abs().maxCoeff();
+                    //cout << "maxAngularDifference:" << maxAngularDifference << endl;
+                    //if (angularDiff.norm() > maximal) // why norm?!
+                    if (maxAngularDifference >  maximal )
+                        //scale = maximal / angularDiff.norm(); // * stepSize;
+                        scale = float(maximal / maxAngularDifference) * stepSize;
+                    dTheta *= scale;
+                }
+
+                // calculate new joint positions after applying deltas
+                theta = thetaOld + dTheta.block(0, 0, nDoF - 6, 1);
+                // check for violation
+                bViolation = false;
+                for (unsigned int i = 0; i < nDoF - 6; i++) {
+                    // lower limit violated?
+                    if (theta[i] < _lLimits[i]) {
+                        // save delta, and apply limit
+                        blockedJointDeltas[i] = _lLimits[i] - thetaOld[i];
+                        theta[i] = _lLimits[i];
+                        blockedJointValues[i] = _lLimits[i];
+                    }
+                    // upper limit violated?
+                    else if (theta[i] > _uLimits[i]) {
+                        // save delta, and apply limit
+                        blockedJointDeltas[i] = _uLimits[i] - thetaOld[i];
+                        theta[i] = _uLimits[i];
+                        blockedJointValues[i] = _uLimits[i];
+                    }
+                    else
+                        // no violation? -> next
+                        continue;
+                    // one limit was violated, so mark this joint as fixed
+                    bViolation = true;
+                    blockedJoints.push_back(i);
+                    // blocking one joint at a time
+                    break;
+                }
+                // abort if no new joints were locked, rerun otherwise
+                if (!bViolation) {
+                    bAbort = true;
+                }
+                /*else {
+                    // todo: check if necessary
+                    rns->setJointValues(blockedJointValues);
+                }*/
+
+            }
+            // restore original robot configuration
+            //rns->setJointValues(thetaOld);
+            // restore real delta theta
+            if (jVerbose)
+            if (blockedJoints.size() != 0)
+                std::cout << "These joints were blocked at their limits: ";
+            for (int index : blockedJoints) {
+                dTheta[index] = blockedJointDeltas[index];
+                if (jVerbose)
+                    std::cout << index << " " << rns->getNode(index)->getName() << "\t";
+            }
+            if (jVerbose)
+            if (blockedJoints.size() != 0)
+                std::cout << std::endl;
+            //cout << "counter:" << counter << endl;
+            return dTheta;
+        } else
+        {
+            // no box constraints
+            error = getError(stepSize);
+            if (jVerbose)
+                cout << "Error Cartesian:" << error.transpose() << endl << endl;
+            Jacobian = getJacobianMatrix();
+            Eigen::MatrixXf pseudoXf = computePseudoInverseJacobianMatrix(Jacobian);
+            if (jVerbose)
+                cout << "PseudoInv min/max:" << endl << pseudoXf.minCoeff() << "," << pseudoXf.maxCoeff() << endl << endl;
+            Eigen::VectorXf dThetaXf = pseudoXf * error;
+            dTheta = dThetaXf;
+            if (jVerbose)
+                cout << "dTheta:" << dTheta.transpose() << endl << endl;
+ 
+            if (considerMaxAngle)
+            {
+                scale = 1.0f;
+                angularDiff.block(0, 0, nDoF - 6, 1) = dTheta.head(nDoF - 6);
+                angularDiff.block(nDoF - 6, 0, 3, 1) = dTheta.tail(3);
+
+                //cout << "angularDiff:" << angularDiff << endl;
+                maxAngularDifference = angularDiff.array().abs().maxCoeff();
+                //maxAngularDifference = angularDiff.norm();
+                //cout << "maxAngularDifference:" << maxAngularDifference << endl;
+                if (maxAngularDifference >  maximal )
+                //if (angularDiff.norm() > maximal)
+                {
+                    scale = maximal / maxAngularDifference;
+                    if (jVerbose)
+                        cout << "Cutting, maxAngularDifference=" << maxAngularDifference << ", scale = " << scale << endl << endl;
+                }
+                dTheta *= scale;
+            }
+            return dTheta;
+        }
+    }
+
+
+    bool RobotPoseDifferentialIK::checkTolerances()
+    {
+        for (auto tcp : tcp_set){
+            if (getErrorPosition(tcp) > tolerancePosition[tcp] || getErrorRotation(tcp)>toleranceRotation[tcp])
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    void RobotPoseDifferentialIK::boxConstraints(bool enable)
+    {
+        considerBoxConstraints = enable;
+    }
+
+    bool RobotPoseDifferentialIK::computeSteps(float stepSize, float minChange, int maxNStep, bool performMinOneStep)
+    {
+        VR_ASSERT(rns);
+        VR_ASSERT(nodes.size() == rns->getSize());
+        VR_ASSERT(robot);
+        std::vector<float> jv(nodes.size(), 0.0f);
+        std::vector<float> jvBest = rns->getJointValues();
+        Eigen::Matrix4f bestPose = robot->getGlobalPose();
+        int step = 0;
+        checkTolerances();
+        float lastDist = getMeanErrorPosition();
+        float bestDist = lastDist;
+        int nrImprovements = 0;
+        this->localJacobians.resize(this->tcp_set.size());
+
+        //cout << verbose << endl;
+        while (step < maxNStep)
+        {
+            Eigen::VectorXf dTheta = this->computeStep(stepSize);
+
+            for (unsigned int i = 0; i < nodes.size(); i++)
+            {
+                jv[i] = (nodes[i]->getJointValue() + dTheta[i]);
+                if (boost::math::isnan(jv[i]) || boost::math::isinf(jv[i]))
+                {
+                    VR_WARNING << "Aborting, invalid joint value (nan)" << endl;
+                    return false;
+                }
+            }
+
+            // update pose
+            Eigen::Matrix3f m;
+            m = Eigen::AngleAxisf(dTheta[nodes.size() + 3], Eigen::Vector3f::UnitX())
+                * Eigen::AngleAxisf(dTheta[nodes.size() + 4], Eigen::Vector3f::UnitY())
+                * Eigen::AngleAxisf(dTheta[nodes.size() + 5], Eigen::Vector3f::UnitZ());
+            Eigen::Vector3f pos(dTheta[nodes.size() + 0], dTheta[nodes.size() + 1], dTheta[nodes.size() + 2]);
+            Eigen::Matrix4f deltaPose = Eigen::Matrix4f::Identity();
+            deltaPose.block(0, 0, 3, 3) = m;
+            deltaPose.block(0, 3, 3, 1) = pos;
+
+            Eigen::Matrix4f resPose = deltaPose * robot->getGlobalPose();
+            robot->setGlobalPose(resPose);
+
+            if (considerBoxConstraints && !rns->checkJointLimits(jv)){
+               VR_ERROR << "Joint limit violated" << endl;
+            }
+            robot->setJointValues(rns, jv);
+
+
+            // check tolerances
+            if (checkTolerances())
+            {
+                if (verbose)
+                    VR_INFO << "Tolerances ok, loop:" << step << endl;
+                return true;
+            }
+
+            float posDist = getMeanErrorPosition();
+
+            // ensure that at least one step is performed (step==0 -> store best solution)
+            if ( (performMinOneStep && step == 0) || posDist<bestDist)
+            {
+                if (verbose && step != 0)
+                    VR_INFO << "Loop:" << step << ", best IK dist: " << posDist << endl;
+
+                bestPose = robot->getGlobalPose();
+                jvBest = jv;
+                bestDist = posDist;
+                nrImprovements++;
+            }
+            if (checkImprovement && posDist>lastDist)
+            {
+                if (verbose)
+                    VR_INFO << "Could not improve result any more (current position error=" << posDist << ", last loop's error:" << lastDist << "), loop:" << step << endl;
+                robot->setGlobalPose(bestPose);
+                robot->setJointValues(rns, jvBest);
+                return false;
+            }
+            float d = dTheta.norm();
+            if (dTheta.norm()<minChange)
+            {
+                if (verbose)
+                    VR_INFO << "Could not improve result any more (dTheta.norm()=" << d << "), loop:" << step << endl;
+
+                // set best result
+                robot->setGlobalPose(bestPose);
+                robot->setJointValues(rns, jvBest);
+                return false; // local minimum
+            }
+
+            lastDist = posDist;
+            step++;
+        }
+
+        // set best result
+        robot->setGlobalPose(bestPose);
+        robot->setJointValues(rns, jvBest);
+        if (verbose && maxNStep > 1)
+        {
+            VR_INFO << "IK failed, improvementSteps:" << nrImprovements << ", loop:" << step << endl;
+            VR_INFO << "pos error:" << getMeanErrorPosition() << endl;
+            VR_INFO << "rot error (tcp 0):" << getErrorRotation(tcp_set[0]) << endl;
+        }
+        return false;
+    }
+
+}
+
diff --git a/VirtualRobot/IK/RobotPoseDifferentialIK.h b/VirtualRobot/IK/RobotPoseDifferentialIK.h
new file mode 100644
index 0000000000000000000000000000000000000000..51b4c3d72d5c01bd669a9e825a53ac1a742e7daa
--- /dev/null
+++ b/VirtualRobot/IK/RobotPoseDifferentialIK.h
@@ -0,0 +1,86 @@
+/**
+* This file is part of Simox.
+*
+* Simox is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* Simox is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* @package    VirtualRobot
+* @author     Nikolaus Vahrenkamp
+* @copyright  2013 Nikolaus Vahrenkamp
+*             GNU Lesser General Public License
+*
+*/
+
+#pragma once
+
+#include "DifferentialIK.h"
+
+#include <string>
+#include <vector>
+
+namespace VirtualRobot
+{
+    class [[deprecated("MMMTools_LegacyConverter")]] VIRTUAL_ROBOT_IMPORT_EXPORT RobotPoseDifferentialIK : public DifferentialIK, public std::enable_shared_from_this<RobotPoseDifferentialIK>
+    {
+    public:
+        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+
+        /*!
+            @brief Initialize a Jacobian object.
+            \param rns The robotNodes (i.e., joints) for which the Jacobians should be calculated.
+            \param coordSystem The coordinate system in which the Jacobians are defined. By default the global coordinate system is used.
+        */
+        RobotPoseDifferentialIK(RobotPtr robot,RobotNodeSetPtr rns, RobotNodePtr coordSystem = RobotNodePtr(), JacobiProvider::InverseJacobiMethod invJacMethod = eSVDDamped);
+
+        Eigen::MatrixXf getJacobianMatrix(SceneObjectPtr tcp, IKSolver::CartesianSelection mode);
+
+        Eigen::MatrixXf getJacobianMatrix();
+
+        /*!	@brief Compute a single IK step.
+            @param stepSize Controls the amount of error to be reduced in each step: \f$ 0 < \beta \leq 1 \f$
+            @return The changes \f$\Delta \theta\f$ in the joint angles.
+            \note{Note} This does not affect the joints values of the robot.
+        */
+        Eigen::VectorXf computeStep(float stepSize=1.0);
+
+        /*!	@brief Computes the complete inverse kinematics.
+            @param stepSize Controls the amount of error to be reduced in each step: \f$ 0 < \beta \leq 1 \f$
+            @param maxSteps Maximal numbers of steps.
+            @param minChange The minimal change in joint angles (euclidean distance in radians)
+            @param performMinOneStep If set, at least one step is performed (helps escaping local minima, but may also cause pose jittering)
+            @note{Note}  Sets the node's joint angles automatically.
+        */
+        bool computeSteps(float stepSize, float minChange, int maxSteps, bool performMinOneStep = true);
+
+        /*!
+            If enabled (standard), joint limits are considered via box constraints.
+        */
+        void boxConstraints(bool enable);
+
+    protected:
+
+        bool checkTolerances();
+
+        Eigen::MatrixXd computePseudoInverseJacobianMatrixDampedD(const Eigen::MatrixXd &m);
+        std::vector<Eigen::MatrixXf> localJacobians;
+        RobotPtr robot;
+
+        bool considerBoxConstraints;
+
+        Eigen::VectorXf _lLimits;
+        Eigen::VectorXf _uLimits;
+    };
+
+    [[deprecated("MMMTools_LegacyConverter")]] typedef std::shared_ptr<RobotPoseDifferentialIK> RobotPoseDifferentialIKPtr;
+}
+
diff --git a/VirtualRobot/XML/rapidxml.hpp b/VirtualRobot/XML/rapidxml.hpp
index 5bc4c0ba537caf44ba65d88e77621425490f4672..7d26fb08cb4d11557caf3818202995463aca3944 100644
--- a/VirtualRobot/XML/rapidxml.hpp
+++ b/VirtualRobot/XML/rapidxml.hpp
@@ -1,2966 +1 @@
-// #pragma once is deliberately not used to make it possible to include both ArmarX and Simox rapidxml
-#ifndef __RAPIDXML_H_INCLUDE__
-#define __RAPIDXML_H_INCLUDE__
-
-// Copyright (C) 2006, 2009 Marcin Kalicinski
-// Version 1.13
-// Revision $DateTime: 2009/05/13 01:46:17 $
-//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
-
-// If standard library is disabled, user must provide implementations of required functions and typedefs
-#if !defined(RAPIDXML_NO_STDLIB)
-#include <cstdlib>      // For std::size_t
-#include <cassert>      // For assert
-#include <new>          // For placement new
-#endif
-
-// On MSVC, disable "conditional expression is constant" warning (level 4).
-// This warning is almost impossible to avoid with certain types of templated code
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4127)   // Conditional expression is constant
-#endif
-
-///////////////////////////////////////////////////////////////////////////
-// RAPIDXML_PARSE_ERROR
-
-#if defined(RAPIDXML_NO_EXCEPTIONS)
-
-#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
-
-namespace rapidxml
-{
-    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
-    //! this function is called to notify user about the error.
-    //! It must be defined by the user.
-    //! <br><br>
-    //! This function cannot return. If it does, the results are undefined.
-    //! <br><br>
-    //! A very simple definition might look like that:
-    //! <pre>
-    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
-    //! {
-    //!     std::cout << "Parse error: " << what << "\n";
-    //!     std::abort();
-    //! }
-    //! </pre>
-    //! \param what Human readable description of the error.
-    //! \param where Pointer to character data where error was detected.
-    void parse_error_handler(const char* what, void* where);
-}
-
-#else
-
-#include <exception>    // For std::exception
-
-#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
-
-namespace rapidxml
-{
-
-    //! Parse error exception.
-    //! This exception is thrown by the parser when an error occurs.
-    //! Use what() function to get human-readable error message.
-    //! Use where() function to get a pointer to position within source text where error was detected.
-    //! <br><br>
-    //! If throwing exceptions by the parser is undesirable,
-    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
-    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
-    //! This function must be defined by the user.
-    //! <br><br>
-    //! This class derives from <code>std::exception</code> class.
-    class parse_error: public std::exception
-    {
-
-    public:
-
-        //! Constructs parse error
-        parse_error(const char* what, void* where)
-            : m_what(what)
-            , m_where(where)
-        {
-        }
-
-        //! Gets human readable description of error.
-        //! \return Pointer to null terminated description of the error.
-        const char* what() const noexcept override
-        {
-            return m_what;
-        }
-
-        //! Gets pointer to character data where error happened.
-        //! Ch should be the same as char type of xml_document that produced the error.
-        //! \return Pointer to location within the parsed string where error occured.
-        template<class Ch>
-        Ch* where() const
-        {
-            return reinterpret_cast<Ch*>(m_where);
-        }
-
-    private:
-
-        const char* m_what;
-        void* m_where;
-
-    };
-}
-
-#endif
-
-///////////////////////////////////////////////////////////////////////////
-// Pool sizes
-
-#ifndef RAPIDXML_STATIC_POOL_SIZE
-// Size of static memory block of memory_pool.
-// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
-// No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
-#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
-#endif
-
-#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
-// Size of dynamic memory block of memory_pool.
-// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
-// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
-#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
-#endif
-
-#ifndef RAPIDXML_ALIGNMENT
-// Memory allocation alignment.
-// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
-// All memory allocations for nodes, attributes and strings will be aligned to this value.
-// This must be a power of 2 and at least 1, otherwise memory_pool will not work.
-#define RAPIDXML_ALIGNMENT sizeof(void *)
-#endif
-
-namespace rapidxml
-{
-    // Forward declarations
-    template<class Ch> class xml_node;
-    template<class Ch> class xml_attribute;
-    template<class Ch> class xml_document;
-
-    //! Enumeration listing all node types produced by the parser.
-    //! Use xml_node::type() function to query node type.
-    enum node_type
-    {
-        node_document,      //!< A document node. Name and value are empty.
-        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
-        node_data,          //!< A data node. Name is empty. Value contains data text.
-        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
-        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
-        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
-        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
-        node_pi             //!< A PI node. Name contains target. Value contains instructions.
-    };
-
-    ///////////////////////////////////////////////////////////////////////
-    // Parsing flags
-
-    //! Parse flag instructing the parser to not create data nodes.
-    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_no_data_nodes = 0x1;
-
-    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
-    //! Can be combined with other flags by use of | operator.
-    //! Note that child data nodes of element node take precendence over its value when printing.
-    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
-    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_no_element_values = 0x2;
-
-    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
-    //! By default zero terminators are placed, modifying source text.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_no_string_terminators = 0x4;
-
-    //! Parse flag instructing the parser to not translate entities in the source text.
-    //! By default entities are translated, modifying source text.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_no_entity_translation = 0x8;
-
-    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
-    //! By default, UTF-8 handling is enabled.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_no_utf8 = 0x10;
-
-    //! Parse flag instructing the parser to create XML declaration node.
-    //! By default, declaration node is not created.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_declaration_node = 0x20;
-
-    //! Parse flag instructing the parser to create comments nodes.
-    //! By default, comment nodes are not created.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_comment_nodes = 0x40;
-
-    //! Parse flag instructing the parser to create DOCTYPE node.
-    //! By default, doctype node is not created.
-    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_doctype_node = 0x80;
-
-    //! Parse flag instructing the parser to create PI nodes.
-    //! By default, PI nodes are not created.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_pi_nodes = 0x100;
-
-    //! Parse flag instructing the parser to validate closing tag names.
-    //! If not set, name inside closing tag is irrelevant to the parser.
-    //! By default, closing tags are not validated.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_validate_closing_tags = 0x200;
-
-    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
-    //! By default, whitespace is not trimmed.
-    //! This flag does not cause the parser to modify source text.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_trim_whitespace = 0x400;
-
-    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
-    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
-    //! By default, whitespace is not normalized.
-    //! If this flag is specified, source text will be modified.
-    //! Can be combined with other flags by use of | operator.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_normalize_whitespace = 0x800;
-
-    // Compound flags
-
-    //! Parse flags which represent default behaviour of the parser.
-    //! This is always equal to 0, so that all other flags can be simply ored together.
-    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
-    //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
-    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
-    //! and using the flag will disable it.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_default = 0;
-
-    //! A combination of parse flags that forbids any modifications of the source text.
-    //! This also results in faster parsing. However, note that the following will occur:
-    //! <ul>
-    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
-    //! <li>entities will not be translated</li>
-    //! <li>whitespace will not be normalized</li>
-    //! </ul>
-    //! See xml_document::parse() function.
-    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
-
-    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
-
-    //! A combination of parse flags resulting in largest amount of data being extracted.
-    //! This usually results in slowest parsing.
-    //! <br><br>
-    //! See xml_document::parse() function.
-    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
-
-    ///////////////////////////////////////////////////////////////////////
-    // Internals
-
-    //! \cond internal
-    namespace internal
-    {
-
-        // Struct that contains lookup tables for the parser
-        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
-        template<int Dummy>
-        struct lookup_tables
-        {
-            static const unsigned char lookup_whitespace[256];              // Whitespace table
-            static const unsigned char lookup_node_name[256];               // Node name table
-            static const unsigned char lookup_text[256];                    // Text table
-            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
-            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
-            static const unsigned char lookup_attribute_name[256];          // Attribute name table
-            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
-            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
-            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
-            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
-            static const unsigned char lookup_digits[256];                  // Digits
-            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
-        };
-
-        // Find length of the string
-        template<class Ch>
-        inline std::size_t measure(const Ch* p)
-        {
-            const Ch* tmp = p;
-
-            while (*tmp)
-            {
-                ++tmp;
-            }
-
-            return tmp - p;
-        }
-
-        // Compare strings for equality
-        template<class Ch>
-        inline bool compare(const Ch* p1, std::size_t size1, const Ch* p2, std::size_t size2, bool case_sensitive)
-        {
-            if (size1 != size2)
-            {
-                return false;
-            }
-
-            if (case_sensitive)
-            {
-                for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2)
-                    if (*p1 != *p2)
-                    {
-                        return false;
-                    }
-            }
-            else
-            {
-                for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2)
-                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
-                    {
-                        return false;
-                    }
-            }
-
-            return true;
-        }
-    }
-    //! \endcond
-
-    ///////////////////////////////////////////////////////////////////////
-    // Memory pool
-
-    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
-    //! In most cases, you will not need to use this class directly.
-    //! However, if you need to create nodes manually or modify names/values of nodes,
-    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
-    //! Not only is this faster than allocating them by using <code>new</code> operator,
-    //! but also their lifetime will be tied to the lifetime of document,
-    //! possibly simplyfing memory management.
-    //! <br><br>
-    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
-    //! You can also call allocate_string() function to allocate strings.
-    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
-    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
-    //! or when the pool is destroyed.
-    //! <br><br>
-    //! It is also possible to create a standalone memory_pool, and use it
-    //! to allocate nodes, whose lifetime will not be tied to any document.
-    //! <br><br>
-    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
-    //! Until static memory is exhausted, no dynamic memory allocations are done.
-    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
-    //! by using global <code>new[]</code> and <code>delete[]</code> operators.
-    //! This behaviour can be changed by setting custom allocation routines.
-    //! Use set_allocator() function to set them.
-    //! <br><br>
-    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
-    //! This value defaults to the size of pointer on target architecture.
-    //! <br><br>
-    //! To obtain absolutely top performance from the parser,
-    //! it is important that all nodes are allocated from a single, contiguous block of memory.
-    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
-    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
-    //! to obtain best wasted memory to performance compromise.
-    //! To do it, define their values before rapidxml.hpp file is included.
-    //! \param Ch Character type of created nodes.
-    template<class Ch = char>
-    class memory_pool
-    {
-
-    public:
-
-        //! \cond internal
-        typedef void* (alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
-        typedef void (free_func)(void*);               // Type of user-defined function used to free memory
-        //! \endcond
-
-        //! Constructs empty pool with default allocator functions.
-        memory_pool()
-            : m_alloc_func(nullptr)
-            , m_free_func(nullptr)
-        {
-            init();
-        }
-
-        //! Destroys pool and frees all the memory.
-        //! This causes memory occupied by nodes allocated by the pool to be freed.
-        //! Nodes allocated from the pool are no longer valid.
-        ~memory_pool()
-        {
-            clear();
-        }
-
-        //! Allocates a new node from the pool, and optionally assigns name and value to it.
-        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
-        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
-        //! will call rapidxml::parse_error_handler() function.
-        //! \param type Type of node to create.
-        //! \param name Name to assign to the node, or 0 to assign no name.
-        //! \param value Value to assign to the node, or 0 to assign no value.
-        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
-        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
-        //! \return Pointer to allocated node. This pointer will never be NULL.
-        xml_node<Ch>* allocate_node(node_type type,
-                                    const Ch* name = nullptr, const Ch* value = nullptr,
-                                    std::size_t name_size = 0, std::size_t value_size = 0)
-        {
-            void* memory = allocate_aligned(sizeof(xml_node<Ch>));
-            xml_node<Ch>* node = new(memory) xml_node<Ch>(type);
-
-            if (name)
-            {
-                if (name_size > 0)
-                {
-                    node->name(name, name_size);
-                }
-                else
-                {
-                    node->name(name);
-                }
-            }
-
-            if (value)
-            {
-                if (value_size > 0)
-                {
-                    node->value(value, value_size);
-                }
-                else
-                {
-                    node->value(value);
-                }
-            }
-
-            return node;
-        }
-
-        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
-        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
-        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
-        //! will call rapidxml::parse_error_handler() function.
-        //! \param name Name to assign to the attribute, or 0 to assign no name.
-        //! \param value Value to assign to the attribute, or 0 to assign no value.
-        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
-        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
-        //! \return Pointer to allocated attribute. This pointer will never be NULL.
-        xml_attribute<Ch>* allocate_attribute(const Ch* name = nullptr, const Ch* value = nullptr,
-                                              std::size_t name_size = 0, std::size_t value_size = 0)
-        {
-            void* memory = allocate_aligned(sizeof(xml_attribute<Ch>));
-            xml_attribute<Ch>* attribute = new(memory) xml_attribute<Ch>;
-
-            if (name)
-            {
-                if (name_size > 0)
-                {
-                    attribute->name(name, name_size);
-                }
-                else
-                {
-                    attribute->name(name);
-                }
-            }
-
-            if (value)
-            {
-                if (value_size > 0)
-                {
-                    attribute->value(value, value_size);
-                }
-                else
-                {
-                    attribute->value(value);
-                }
-            }
-
-            return attribute;
-        }
-
-        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
-        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
-        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
-        //! will call rapidxml::parse_error_handler() function.
-        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
-        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
-        //! \return Pointer to allocated char array. This pointer will never be NULL.
-        Ch* allocate_string(const Ch* source = 0, std::size_t size = 0)
-        {
-            assert(source || size);     // Either source or size (or both) must be specified
-
-            if (size == 0)
-            {
-                size = internal::measure(source) + 1;
-            }
-
-            Ch* result = static_cast<Ch*>(allocate_aligned(size * sizeof(Ch)));
-
-            if (source)
-                for (std::size_t i = 0; i < size; ++i)
-                {
-                    result[i] = source[i];
-                }
-
-            return result;
-        }
-
-        //! Clones an xml_node and its hierarchy of child nodes and attributes.
-        //! Nodes and attributes are allocated from this memory pool.
-        //! Names and values are not cloned, they are shared between the clone and the source.
-        //! Result node can be optionally specified as a second parameter,
-        //! in which case its contents will be replaced with cloned source node.
-        //! This is useful when you want to clone entire document.
-        //! \param source Node to clone.
-        //! \param result Node to put results in, or 0 to automatically allocate result node
-        //! \return Pointer to cloned node. This pointer will never be NULL.
-        xml_node<Ch>* clone_node(const xml_node<Ch>* source, xml_node<Ch>* result = 0)
-        {
-            // Prepare result node
-            if (result)
-            {
-                result->remove_all_attributes();
-                result->remove_all_nodes();
-                result->type(source->type());
-            }
-            else
-            {
-                result = allocate_node(source->type());
-            }
-
-            // Clone name and value
-            result->name(source->name(), source->name_size());
-            result->value(source->value(), source->value_size());
-
-            // Clone child nodes and attributes
-            for (xml_node<Ch>* child = source->first_node(); child; child = child->next_sibling())
-            {
-                result->append_node(clone_node(child));
-            }
-
-            for (xml_attribute<Ch>* attr = source->first_attribute(); attr; attr = attr->next_attribute())
-            {
-                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
-            }
-
-            return result;
-        }
-
-        //! Clears the pool.
-        //! This causes memory occupied by nodes allocated by the pool to be freed.
-        //! Any nodes or strings allocated from the pool will no longer be valid.
-        void clear()
-        {
-            while (m_begin != m_static_memory)
-            {
-                char* previous_begin = reinterpret_cast<header*>(align(m_begin))->previous_begin;
-
-                if (m_free_func)
-                {
-                    m_free_func(m_begin);
-                }
-                else
-                {
-                    delete[] m_begin;
-                }
-
-                m_begin = previous_begin;
-            }
-
-            init();
-        }
-
-        //! Sets or resets the user-defined memory allocation functions for the pool.
-        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
-        //! Allocation function must not return invalid pointer on failure. It should either throw,
-        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
-        //! If it returns invalid pointer, results are undefined.
-        //! <br><br>
-        //! User defined allocation functions must have the following forms:
-        //! <br><code>
-        //! <br>void *allocate(std::size_t size);
-        //! <br>void free(void *pointer);
-        //! </code><br>
-        //! \param af Allocation function, or 0 to restore default function
-        //! \param ff Free function, or 0 to restore default function
-        void set_allocator(alloc_func* af, free_func* ff)
-        {
-            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
-            m_alloc_func = af;
-            m_free_func = ff;
-        }
-
-    private:
-
-        struct header
-        {
-            char* previous_begin;
-        };
-
-        void init()
-        {
-            m_begin = m_static_memory;
-            m_ptr = align(m_begin);
-            m_end = m_static_memory + sizeof(m_static_memory);
-        }
-
-        char* align(char* ptr)
-        {
-            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
-            return ptr + alignment;
-        }
-
-        char* allocate_raw(std::size_t size)
-        {
-            // Allocate
-            void* memory;
-
-            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
-            {
-                memory = m_alloc_func(size);
-                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
-            }
-            else
-            {
-                memory = new char[size];
-#ifdef RAPIDXML_NO_EXCEPTIONS
-
-                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
-                {
-                    RAPIDXML_PARSE_ERROR("out of memory", 0);
-                }
-
-#endif
-            }
-
-            return static_cast<char*>(memory);
-        }
-
-        void* allocate_aligned(std::size_t size)
-        {
-            // Calculate aligned pointer
-            char* result = align(m_ptr);
-
-            // If not enough memory left in current pool, allocate a new pool
-            if (result + size > m_end)
-            {
-                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
-                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
-
-                if (pool_size < size)
-                {
-                    pool_size = size;
-                }
-
-                // Allocate
-                std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
-                char* raw_memory = allocate_raw(alloc_size);
-
-                // Setup new pool in allocated memory
-                char* pool = align(raw_memory);
-                header* new_header = reinterpret_cast<header*>(pool);
-                new_header->previous_begin = m_begin;
-                m_begin = raw_memory;
-                m_ptr = pool + sizeof(header);
-                m_end = raw_memory + alloc_size;
-
-                // Calculate aligned pointer again using new pool
-                result = align(m_ptr);
-            }
-
-            // Update pool and return aligned pointer
-            m_ptr = result + size;
-            return result;
-        }
-
-        char* m_begin;                                      // Start of raw memory making up current pool
-        char* m_ptr;                                        // First free byte in current pool
-        char* m_end;                                        // One past last available byte in current pool
-        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
-        alloc_func* m_alloc_func;                           // Allocator function, or 0 if default is to be used
-        free_func* m_free_func;                             // Free function, or 0 if default is to be used
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    // XML base
-
-    //! Base class for xml_node and xml_attribute implementing common functions:
-    //! name(), name_size(), value(), value_size() and parent().
-    //! \param Ch Character type to use
-    template<class Ch = char>
-    class xml_base
-    {
-
-    public:
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Construction & destruction
-
-        // Construct a base with empty name, value and parent
-        xml_base()
-            : m_name(nullptr)
-            , m_value(nullptr)
-            , m_parent(nullptr)
-        {
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Node data access
-
-        //! Gets name of the node.
-        //! Interpretation of name depends on type of node.
-        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
-        //! <br><br>
-        //! Use name_size() function to determine length of the name.
-        //! \return Name of node, or empty string if node has no name.
-        Ch* name() const
-        {
-            return m_name ? m_name : nullstr();
-        }
-
-        //! Gets size of node name, not including terminator character.
-        //! This function works correctly irrespective of whether name is or is not zero terminated.
-        //! \return Size of node name, in characters.
-        std::size_t name_size() const
-        {
-            return m_name ? m_name_size : 0;
-        }
-
-        //! Gets value of node.
-        //! Interpretation of value depends on type of node.
-        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
-        //! <br><br>
-        //! Use value_size() function to determine length of the value.
-        //! \return Value of node, or empty string if node has no value.
-        Ch* value() const
-        {
-            return m_value ? m_value : nullstr();
-        }
-
-        //! Gets size of node value, not including terminator character.
-        //! This function works correctly irrespective of whether value is or is not zero terminated.
-        //! \return Size of node value, in characters.
-        std::size_t value_size() const
-        {
-            return m_value ? m_value_size : 0;
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Node modification
-
-        //! Sets name of node to a non zero-terminated string.
-        //! See \ref ownership_of_strings.
-        //! <br><br>
-        //! Note that node does not own its name or value, it only stores a pointer to it.
-        //! It will not delete or otherwise free the pointer on destruction.
-        //! It is reponsibility of the user to properly manage lifetime of the string.
-        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
-        //! on destruction of the document the string will be automatically freed.
-        //! <br><br>
-        //! Size of name must be specified separately, because name does not have to be zero terminated.
-        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
-        //! \param name Name of node to set. Does not have to be zero terminated.
-        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
-        void name(const Ch* name, std::size_t size)
-        {
-            m_name = const_cast<Ch*>(name);
-            m_name_size = size;
-        }
-
-        //! Sets name of node to a zero-terminated string.
-        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
-        //! \param name Name of node to set. Must be zero terminated.
-        void name(const Ch* name)
-        {
-            this->name(name, internal::measure(name));
-        }
-
-        //! Sets value of node to a non zero-terminated string.
-        //! See \ref ownership_of_strings.
-        //! <br><br>
-        //! Note that node does not own its name or value, it only stores a pointer to it.
-        //! It will not delete or otherwise free the pointer on destruction.
-        //! It is reponsibility of the user to properly manage lifetime of the string.
-        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
-        //! on destruction of the document the string will be automatically freed.
-        //! <br><br>
-        //! Size of value must be specified separately, because it does not have to be zero terminated.
-        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
-        //! <br><br>
-        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
-        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
-        //! \param value value of node to set. Does not have to be zero terminated.
-        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
-        void value(const Ch* value, std::size_t size)
-        {
-            m_value = const_cast<Ch*>(value);
-            m_value_size = size;
-        }
-
-        //! Sets value of node to a zero-terminated string.
-        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
-        //! \param value Vame of node to set. Must be zero terminated.
-        void value(const Ch* value)
-        {
-            this->value(value, internal::measure(value));
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Related nodes access
-
-        //! Gets node parent.
-        //! \return Pointer to parent node, or 0 if there is no parent.
-        xml_node<Ch>* parent() const
-        {
-            return m_parent;
-        }
-
-    protected:
-
-        // Return empty string
-        static Ch* nullstr()
-        {
-            static Ch zero = Ch('\0');
-            return &zero;
-        }
-
-        Ch* m_name;                         // Name of node, or 0 if no name
-        Ch* m_value;                        // Value of node, or 0 if no value
-        std::size_t m_name_size;            // Length of node name, or undefined of no name
-        std::size_t m_value_size;           // Length of node value, or undefined if no value
-        xml_node<Ch>* m_parent;             // Pointer to parent node, or 0 if none
-
-    };
-
-    //! Class representing attribute node of XML document.
-    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
-    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
-    //! Thus, this text must persist in memory for the lifetime of attribute.
-    //! \param Ch Character type to use.
-    template<class Ch = char>
-    class xml_attribute: public xml_base<Ch>
-    {
-
-        friend class xml_node<Ch>;
-
-    public:
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Construction & destruction
-
-        //! Constructs an empty attribute with the specified type.
-        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
-        xml_attribute()
-        {
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Related nodes access
-
-        //! Gets document of which attribute is a child.
-        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
-        xml_document<Ch>* document() const
-        {
-            if (xml_node<Ch>* node = this->parent())
-            {
-                while (node->parent())
-                {
-                    node = node->parent();
-                }
-
-                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
-            }
-            else
-            {
-                return 0;
-            }
-        }
-
-        //! Gets previous attribute, optionally matching attribute name.
-        //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found attribute, or 0 if not found.
-        xml_attribute<Ch>* previous_attribute(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_attribute<Ch>* attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
-                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
-                    {
-                        return attribute;
-                    }
-
-                return 0;
-            }
-            else
-            {
-                return this->m_parent ? m_prev_attribute : 0;
-            }
-        }
-
-        //! Gets next attribute, optionally matching attribute name.
-        //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found attribute, or 0 if not found.
-        xml_attribute<Ch>* next_attribute(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_attribute<Ch>* attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
-                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
-                    {
-                        return attribute;
-                    }
-
-                return nullptr;
-            }
-            else
-            {
-                return this->m_parent ? m_next_attribute : nullptr;
-            }
-        }
-
-    private:
-
-        xml_attribute<Ch>* m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
-        xml_attribute<Ch>* m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
-
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    // XML node
-
-    //! Class representing a node of XML document.
-    //! Each node may have associated name and value strings, which are available through name() and value() functions.
-    //! Interpretation of name and value depends on type of the node.
-    //! Type of node can be determined by using type() function.
-    //! <br><br>
-    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
-    //! Thus, this text must persist in the memory for the lifetime of node.
-    //! \param Ch Character type to use.
-    template<class Ch = char>
-    class xml_node: public xml_base<Ch>
-    {
-
-    public:
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Construction & destruction
-
-        //! Constructs an empty node with the specified type.
-        //! Consider using memory_pool of appropriate document to allocate nodes manually.
-        //! \param type Type of node to construct.
-        xml_node(node_type type)
-            : m_type(type)
-            , m_first_node(nullptr)
-            , m_first_attribute(nullptr)
-        {
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Node data access
-
-        //! Gets type of node.
-        //! \return Type of node.
-        node_type type() const
-        {
-            return m_type;
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Related nodes access
-
-        //! Gets document of which node is a child.
-        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
-        xml_document<Ch>* document() const
-        {
-            xml_node<Ch>* node = const_cast<xml_node<Ch> *>(this);
-
-            while (node->parent())
-            {
-                node = node->parent();
-            }
-
-            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
-        }
-
-        //! Gets first child node, optionally matching node name.
-        //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found child, or 0 if not found.
-        xml_node<Ch>* first_node(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_node<Ch>* child = m_first_node; child; child = child->next_sibling())
-                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
-                    {
-                        return child;
-                    }
-
-                return nullptr;
-            }
-            else
-            {
-                return m_first_node;
-            }
-        }
-
-        //! Gets last child node, optionally matching node name.
-        //! Behaviour is undefined if node has no children.
-        //! Use first_node() to test if node has children.
-        //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found child, or 0 if not found.
-        xml_node<Ch>* last_node(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            assert(m_first_node);  // Cannot query for last child if node has no children
-
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_node<Ch>* child = m_last_node; child; child = child->previous_sibling())
-                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
-                    {
-                        return child;
-                    }
-
-                return 0;
-            }
-            else
-            {
-                return m_last_node;
-            }
-        }
-
-        //! Gets previous sibling node, optionally matching node name.
-        //! Behaviour is undefined if node has no parent.
-        //! Use parent() to test if node has a parent.
-        //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found sibling, or 0 if not found.
-        xml_node<Ch>* previous_sibling(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            assert(this->m_parent);     // Cannot query for siblings if node has no parent
-
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_node<Ch>* sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
-                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
-                    {
-                        return sibling;
-                    }
-
-                return 0;
-            }
-            else
-            {
-                return m_prev_sibling;
-            }
-        }
-
-        //! Gets next sibling node, optionally matching node name.
-        //! Behaviour is undefined if node has no parent.
-        //! Use parent() to test if node has a parent.
-        //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found sibling, or 0 if not found.
-        xml_node<Ch>* next_sibling(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            assert(this->m_parent);     // Cannot query for siblings if node has no parent
-
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_node<Ch>* sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
-                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
-                    {
-                        return sibling;
-                    }
-
-                return nullptr;
-            }
-            else
-            {
-                return m_next_sibling;
-            }
-        }
-
-        //! Gets first attribute of node, optionally matching attribute name.
-        //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found attribute, or 0 if not found.
-        xml_attribute<Ch>* first_attribute(const Ch* name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_attribute<Ch>* attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
-                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
-                    {
-                        return attribute;
-                    }
-
-                return nullptr;
-            }
-            else
-            {
-                return m_first_attribute;
-            }
-        }
-
-        //! Gets last attribute of node, optionally matching attribute name.
-        //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
-        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
-        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
-        //! \return Pointer to found attribute, or 0 if not found.
-        xml_attribute<Ch>* last_attribute(const Ch* name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
-        {
-            if (name)
-            {
-                if (name_size == 0)
-                {
-                    name_size = internal::measure(name);
-                }
-
-                for (xml_attribute<Ch>* attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
-                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
-                    {
-                        return attribute;
-                    }
-
-                return 0;
-            }
-            else
-            {
-                return m_first_attribute ? m_last_attribute : 0;
-            }
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Node modification
-
-        //! Sets type of node.
-        //! \param type Type of node to set.
-        void type(node_type type)
-        {
-            m_type = type;
-        }
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Node manipulation
-
-        //! Prepends a new child node.
-        //! The prepended child becomes the first child, and all existing children are moved one position back.
-        //! \param child Node to prepend.
-        void prepend_node(xml_node<Ch>* child)
-        {
-            assert(child && !child->parent() && child->type() != node_document);
-
-            if (first_node())
-            {
-                child->m_next_sibling = m_first_node;
-                m_first_node->m_prev_sibling = child;
-            }
-            else
-            {
-                child->m_next_sibling = 0;
-                m_last_node = child;
-            }
-
-            m_first_node = child;
-            child->m_parent = this;
-            child->m_prev_sibling = 0;
-        }
-
-        //! Appends a new child node.
-        //! The appended child becomes the last child.
-        //! \param child Node to append.
-        void append_node(xml_node<Ch>* child)
-        {
-            assert(child && !child->parent() && child->type() != node_document);
-
-            if (first_node())
-            {
-                child->m_prev_sibling = m_last_node;
-                m_last_node->m_next_sibling = child;
-            }
-            else
-            {
-                child->m_prev_sibling = nullptr;
-                m_first_node = child;
-            }
-
-            m_last_node = child;
-            child->m_parent = this;
-            child->m_next_sibling = nullptr;
-        }
-
-        //! Inserts a new child node at specified place inside the node.
-        //! All children after and including the specified node are moved one position back.
-        //! \param where Place where to insert the child, or 0 to insert at the back.
-        //! \param child Node to insert.
-        void insert_node(xml_node<Ch>* where, xml_node<Ch>* child)
-        {
-            assert(!where || where->parent() == this);
-            assert(child && !child->parent() && child->type() != node_document);
-
-            if (where == m_first_node)
-            {
-                prepend_node(child);
-            }
-            else if (where == 0)
-            {
-                append_node(child);
-            }
-            else
-            {
-                child->m_prev_sibling = where->m_prev_sibling;
-                child->m_next_sibling = where;
-                where->m_prev_sibling->m_next_sibling = child;
-                where->m_prev_sibling = child;
-                child->m_parent = this;
-            }
-        }
-
-        //! Removes first child node.
-        //! If node has no children, behaviour is undefined.
-        //! Use first_node() to test if node has children.
-        void remove_first_node()
-        {
-            assert(first_node());
-            xml_node<Ch>* child = m_first_node;
-            m_first_node = child->m_next_sibling;
-
-            if (child->m_next_sibling)
-            {
-                child->m_next_sibling->m_prev_sibling = 0;
-            }
-            else
-            {
-                m_last_node = 0;
-            }
-
-            child->m_parent = 0;
-        }
-
-        //! Removes last child of the node.
-        //! If node has no children, behaviour is undefined.
-        //! Use first_node() to test if node has children.
-        void remove_last_node()
-        {
-            assert(first_node());
-            xml_node<Ch>* child = m_last_node;
-
-            if (child->m_prev_sibling)
-            {
-                m_last_node = child->m_prev_sibling;
-                child->m_prev_sibling->m_next_sibling = 0;
-            }
-            else
-            {
-                m_first_node = 0;
-            }
-
-            child->m_parent = 0;
-        }
-
-        //! Removes specified child from the node
-        // \param where Pointer to child to be removed.
-        void remove_node(xml_node<Ch>* where)
-        {
-            assert(where && where->parent() == this);
-            assert(first_node());
-
-            if (where == m_first_node)
-            {
-                remove_first_node();
-            }
-            else if (where == m_last_node)
-            {
-                remove_last_node();
-            }
-            else
-            {
-                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
-                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
-                where->m_parent = 0;
-            }
-        }
-
-        //! Removes all child nodes (but not attributes).
-        void remove_all_nodes()
-        {
-            for (xml_node<Ch>* node = first_node(); node; node = node->m_next_sibling)
-            {
-                node->m_parent = nullptr;
-            }
-
-            m_first_node = nullptr;
-        }
-
-        //! Prepends a new attribute to the node.
-        //! \param attribute Attribute to prepend.
-        void prepend_attribute(xml_attribute<Ch>* attribute)
-        {
-            assert(attribute && !attribute->parent());
-
-            if (first_attribute())
-            {
-                attribute->m_next_attribute = m_first_attribute;
-                m_first_attribute->m_prev_attribute = attribute;
-            }
-            else
-            {
-                attribute->m_next_attribute = 0;
-                m_last_attribute = attribute;
-            }
-
-            m_first_attribute = attribute;
-            attribute->m_parent = this;
-            attribute->m_prev_attribute = 0;
-        }
-
-        //! Appends a new attribute to the node.
-        //! \param attribute Attribute to append.
-        void append_attribute(xml_attribute<Ch>* attribute)
-        {
-            assert(attribute && !attribute->parent());
-
-            if (first_attribute())
-            {
-                attribute->m_prev_attribute = m_last_attribute;
-                m_last_attribute->m_next_attribute = attribute;
-            }
-            else
-            {
-                attribute->m_prev_attribute = nullptr;
-                m_first_attribute = attribute;
-            }
-
-            m_last_attribute = attribute;
-            attribute->m_parent = this;
-            attribute->m_next_attribute = nullptr;
-        }
-
-        //! Inserts a new attribute at specified place inside the node.
-        //! All attributes after and including the specified attribute are moved one position back.
-        //! \param where Place where to insert the attribute, or 0 to insert at the back.
-        //! \param attribute Attribute to insert.
-        void insert_attribute(xml_attribute<Ch>* where, xml_attribute<Ch>* attribute)
-        {
-            assert(!where || where->parent() == this);
-            assert(attribute && !attribute->parent());
-
-            if (where == m_first_attribute)
-            {
-                prepend_attribute(attribute);
-            }
-            else if (where == 0)
-            {
-                append_attribute(attribute);
-            }
-            else
-            {
-                attribute->m_prev_attribute = where->m_prev_attribute;
-                attribute->m_next_attribute = where;
-                where->m_prev_attribute->m_next_attribute = attribute;
-                where->m_prev_attribute = attribute;
-                attribute->m_parent = this;
-            }
-        }
-
-        //! Removes first attribute of the node.
-        //! If node has no attributes, behaviour is undefined.
-        //! Use first_attribute() to test if node has attributes.
-        void remove_first_attribute()
-        {
-            assert(first_attribute());
-            xml_attribute<Ch>* attribute = m_first_attribute;
-
-            if (attribute->m_next_attribute)
-            {
-                attribute->m_next_attribute->m_prev_attribute = 0;
-            }
-            else
-            {
-                m_last_attribute = 0;
-            }
-
-            attribute->m_parent = 0;
-            m_first_attribute = attribute->m_next_attribute;
-        }
-
-        //! Removes last attribute of the node.
-        //! If node has no attributes, behaviour is undefined.
-        //! Use first_attribute() to test if node has attributes.
-        void remove_last_attribute()
-        {
-            assert(first_attribute());
-            xml_attribute<Ch>* attribute = m_last_attribute;
-
-            if (attribute->m_prev_attribute)
-            {
-                attribute->m_prev_attribute->m_next_attribute = 0;
-                m_last_attribute = attribute->m_prev_attribute;
-            }
-            else
-            {
-                m_first_attribute = 0;
-            }
-
-            attribute->m_parent = 0;
-        }
-
-        //! Removes specified attribute from node.
-        //! \param where Pointer to attribute to be removed.
-        void remove_attribute(xml_attribute<Ch>* where)
-        {
-            assert(first_attribute() && where->parent() == this);
-
-            if (where == m_first_attribute)
-            {
-                remove_first_attribute();
-            }
-            else if (where == m_last_attribute)
-            {
-                remove_last_attribute();
-            }
-            else
-            {
-                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
-                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
-                where->m_parent = 0;
-            }
-        }
-
-        //! Removes all attributes of node.
-        void remove_all_attributes()
-        {
-            for (xml_attribute<Ch>* attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
-            {
-                attribute->m_parent = nullptr;
-            }
-
-            m_first_attribute = nullptr;
-        }
-
-    private:
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Restrictions
-
-        // No copying
-        xml_node(const xml_node&);
-        void operator =(const xml_node&);
-
-        ///////////////////////////////////////////////////////////////////////////
-        // Data members
-
-        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
-        // This is required for maximum performance, as it allows the parser to omit initialization of
-        // unneded/redundant values.
-        //
-        // The rules are as follows:
-        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
-        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
-        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
-
-        node_type m_type;                       // Type of node; always valid
-        xml_node<Ch>* m_first_node;             // Pointer to first child node, or 0 if none; always valid
-        xml_node<Ch>* m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
-        xml_attribute<Ch>* m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
-        xml_attribute<Ch>* m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
-        xml_node<Ch>* m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
-        xml_node<Ch>* m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
-
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    // XML document
-
-    //! This class represents root of the DOM hierarchy.
-    //! It is also an xml_node and a memory_pool through public inheritance.
-    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
-    //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
-    //! which are inherited from memory_pool.
-    //! To access root node of the document, use the document itself, as if it was an xml_node.
-    //! \param Ch Character type to use.
-    template<class Ch = char>
-    class xml_document: public xml_node<Ch>, public memory_pool<Ch>
-    {
-
-    public:
-
-        //! Constructs empty XML document
-        xml_document()
-            : xml_node<Ch>(node_document)
-        {
-        }
-
-        //! Parses zero-terminated XML string according to given flags.
-        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
-        //! The string must persist for the lifetime of the document.
-        //! In case of error, rapidxml::parse_error exception will be thrown.
-        //! <br><br>
-        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
-        //! Make sure that data is zero-terminated.
-        //! <br><br>
-        //! Document can be parsed into multiple times.
-        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
-        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
-        template<int Flags>
-        void parse(Ch* text)
-        {
-            assert(text);
-
-            // Remove current contents
-            this->remove_all_nodes();
-            this->remove_all_attributes();
-
-            // Parse BOM, if any
-            parse_bom<Flags>(text);
-
-            // Parse children
-            while (1)
-            {
-                // Skip whitespace before node
-                skip<whitespace_pred, Flags>(text);
-
-                if (*text == 0)
-                {
-                    break;
-                }
-
-                // Parse and append new child
-                if (*text == Ch('<'))
-                {
-                    ++text;     // Skip '<'
-
-                    if (xml_node<Ch>* node = parse_node<Flags>(text))
-                    {
-                        this->append_node(node);
-                    }
-                }
-                else
-                {
-                    RAPIDXML_PARSE_ERROR("expected <", text);
-                }
-            }
-
-        }
-
-        //! Clears the document by deleting all nodes and clearing the memory pool.
-        //! All nodes owned by document pool are destroyed.
-        void clear()
-        {
-            this->remove_all_nodes();
-            this->remove_all_attributes();
-            memory_pool<Ch>::clear();
-        }
-
-    private:
-
-        ///////////////////////////////////////////////////////////////////////
-        // Internal character utility functions
-
-        // Detect whitespace character
-        struct whitespace_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect node name character
-        struct node_name_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect attribute name character
-        struct attribute_name_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect text character (PCDATA)
-        struct text_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect text character (PCDATA) that does not require processing
-        struct text_pure_no_ws_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect text character (PCDATA) that does not require processing
-        struct text_pure_with_ws_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
-            }
-        };
-
-        // Detect attribute value character
-        template<Ch Quote>
-        struct attribute_value_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                if (Quote == Ch('\''))
-                {
-                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
-                }
-
-                if (Quote == Ch('\"'))
-                {
-                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
-                }
-
-                return 0;       // Should never be executed, to avoid warnings on Comeau
-            }
-        };
-
-        // Detect attribute value character
-        template<Ch Quote>
-        struct attribute_value_pure_pred
-        {
-            static unsigned char test(Ch ch)
-            {
-                if (Quote == Ch('\''))
-                {
-                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
-                }
-
-                if (Quote == Ch('\"'))
-                {
-                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
-                }
-
-                return 0;       // Should never be executed, to avoid warnings on Comeau
-            }
-        };
-
-        // Insert coded character, using UTF8 or 8-bit ASCII
-        template<int Flags>
-        static void insert_coded_character(Ch*& text, unsigned long code)
-        {
-            if (Flags & parse_no_utf8)
-            {
-                // Insert 8-bit ASCII character
-                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
-                text[0] = static_cast<unsigned char>(code);
-                text += 1;
-            }
-            else
-            {
-                // Insert UTF8 sequence
-                if (code < 0x80)    // 1 byte sequence
-                {
-                    text[0] = static_cast<unsigned char>(code);
-                    text += 1;
-                }
-                else if (code < 0x800)  // 2 byte sequence
-                {
-                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[0] = static_cast<unsigned char>(code | 0xC0);
-                    text += 2;
-                }
-                else if (code < 0x10000)    // 3 byte sequence
-                {
-                    text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[0] = static_cast<unsigned char>(code | 0xE0);
-                    text += 3;
-                }
-                else if (code < 0x110000)   // 4 byte sequence
-                {
-                    text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF);
-                    code >>= 6;
-                    text[0] = static_cast<unsigned char>(code | 0xF0);
-                    text += 4;
-                }
-                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
-                {
-                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
-                }
-            }
-        }
-
-        // Skip characters until predicate evaluates to true
-        template<class StopPred, int Flags>
-        static void skip(Ch*& text)
-        {
-            Ch* tmp = text;
-
-            while (StopPred::test(*tmp))
-            {
-                ++tmp;
-            }
-
-            text = tmp;
-        }
-
-        // Skip characters until predicate evaluates to true while doing the following:
-        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
-        // - condensing whitespace sequences to single space character
-        template<class StopPred, class StopPredPure, int Flags>
-        static Ch* skip_and_expand_character_refs(Ch*& text)
-        {
-            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
-            if (Flags & parse_no_entity_translation &&
-                !(Flags & parse_normalize_whitespace) &&
-                !(Flags & parse_trim_whitespace))
-            {
-                skip<StopPred, Flags>(text);
-                return text;
-            }
-
-            // Use simple skip until first modification is detected
-            skip<StopPredPure, Flags>(text);
-
-            // Use translation skip
-            Ch* src = text;
-            Ch* dest = src;
-
-            while (StopPred::test(*src))
-            {
-                // If entity translation is enabled
-                if (!(Flags & parse_no_entity_translation))
-                {
-                    // Test if replacement is needed
-                    if (src[0] == Ch('&'))
-                    {
-                        switch (src[1])
-                        {
-
-                            // &amp; &apos;
-                            case Ch('a'):
-                                if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
-                                {
-                                    *dest = Ch('&');
-                                    ++dest;
-                                    src += 5;
-                                    continue;
-                                }
-
-                                if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
-                                {
-                                    *dest = Ch('\'');
-                                    ++dest;
-                                    src += 6;
-                                    continue;
-                                }
-
-                                break;
-
-                            // &quot;
-                            case Ch('q'):
-                                if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
-                                {
-                                    *dest = Ch('"');
-                                    ++dest;
-                                    src += 6;
-                                    continue;
-                                }
-
-                                break;
-
-                            // &gt;
-                            case Ch('g'):
-                                if (src[2] == Ch('t') && src[3] == Ch(';'))
-                                {
-                                    *dest = Ch('>');
-                                    ++dest;
-                                    src += 4;
-                                    continue;
-                                }
-
-                                break;
-
-                            // &lt;
-                            case Ch('l'):
-                                if (src[2] == Ch('t') && src[3] == Ch(';'))
-                                {
-                                    *dest = Ch('<');
-                                    ++dest;
-                                    src += 4;
-                                    continue;
-                                }
-
-                                break;
-
-                            // &#...; - assumes ASCII
-                            case Ch('#'):
-                                if (src[2] == Ch('x'))
-                                {
-                                    unsigned long code = 0;
-                                    src += 3;   // Skip &#x
-
-                                    while (1)
-                                    {
-                                        unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
-
-                                        if (digit == 0xFF)
-                                        {
-                                            break;
-                                        }
-
-                                        code = code * 16 + digit;
-                                        ++src;
-                                    }
-
-                                    insert_coded_character<Flags>(dest, code);    // Put character in output
-                                }
-                                else
-                                {
-                                    unsigned long code = 0;
-                                    src += 2;   // Skip &#
-
-                                    while (1)
-                                    {
-                                        unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
-
-                                        if (digit == 0xFF)
-                                        {
-                                            break;
-                                        }
-
-                                        code = code * 10 + digit;
-                                        ++src;
-                                    }
-
-                                    insert_coded_character<Flags>(dest, code);    // Put character in output
-                                }
-
-                                if (*src == Ch(';'))
-                                {
-                                    ++src;
-                                }
-                                else
-                                {
-                                    RAPIDXML_PARSE_ERROR("expected ;", src);
-                                }
-
-                                continue;
-
-                            // Something else
-                            default:
-                                // Ignore, just copy '&' verbatim
-                                break;
-
-                        }
-                    }
-                }
-
-                // If whitespace condensing is enabled
-                if (Flags & parse_normalize_whitespace)
-                {
-                    // Test if condensing is needed
-                    if (whitespace_pred::test(*src))
-                    {
-                        *dest = Ch(' ');
-                        ++dest;    // Put single space in dest
-                        ++src;                      // Skip first whitespace char
-
-                        // Skip remaining whitespace chars
-                        while (whitespace_pred::test(*src))
-                        {
-                            ++src;
-                        }
-
-                        continue;
-                    }
-                }
-
-                // No replacement, only copy character
-                *dest++ = *src++;
-
-            }
-
-            // Return new end
-            text = src;
-            return dest;
-
-        }
-
-        ///////////////////////////////////////////////////////////////////////
-        // Internal parsing functions
-
-        // Parse BOM, if any
-        template<int Flags>
-        void parse_bom(Ch*& text)
-        {
-            // UTF-8?
-            if (static_cast<unsigned char>(text[0]) == 0xEF &&
-                static_cast<unsigned char>(text[1]) == 0xBB &&
-                static_cast<unsigned char>(text[2]) == 0xBF)
-            {
-                text += 3;      // Skup utf-8 bom
-            }
-        }
-
-        // Parse XML declaration (<?xml...)
-        template<int Flags>
-        xml_node<Ch>* parse_xml_declaration(Ch*& text)
-        {
-            // If parsing of declaration is disabled
-            if (!(Flags & parse_declaration_node))
-            {
-                // Skip until end of declaration
-                while (text[0] != Ch('?') || text[1] != Ch('>'))
-                {
-                    if (!text[0])
-                    {
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                    }
-
-                    ++text;
-                }
-
-                text += 2;    // Skip '?>'
-                return nullptr;
-            }
-
-            // Create declaration
-            xml_node<Ch>* declaration = this->allocate_node(node_declaration);
-
-            // Skip whitespace before attributes or ?>
-            skip<whitespace_pred, Flags>(text);
-
-            // Parse declaration attributes
-            parse_node_attributes<Flags>(text, declaration);
-
-            // Skip ?>
-            if (text[0] != Ch('?') || text[1] != Ch('>'))
-            {
-                RAPIDXML_PARSE_ERROR("expected ?>", text);
-            }
-
-            text += 2;
-
-            return declaration;
-        }
-
-        // Parse XML comment (<!--...)
-        template<int Flags>
-        xml_node<Ch>* parse_comment(Ch*& text)
-        {
-            // If parsing of comments is disabled
-            if (!(Flags & parse_comment_nodes))
-            {
-                // Skip until end of comment
-                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
-                {
-                    if (!text[0])
-                    {
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                    }
-
-                    ++text;
-                }
-
-                text += 3;     // Skip '-->'
-                return nullptr;      // Do not produce comment node
-            }
-
-            // Remember value start
-            Ch* value = text;
-
-            // Skip until end of comment
-            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
-            {
-                if (!text[0])
-                {
-                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                }
-
-                ++text;
-            }
-
-            // Create comment node
-            xml_node<Ch>* comment = this->allocate_node(node_comment);
-            comment->value(value, text - value);
-
-            // Place zero terminator after comment value
-            if (!(Flags & parse_no_string_terminators))
-            {
-                *text = Ch('\0');
-            }
-
-            text += 3;     // Skip '-->'
-            return comment;
-        }
-
-        // Parse DOCTYPE
-        template<int Flags>
-        xml_node<Ch>* parse_doctype(Ch*& text)
-        {
-            // Remember value start
-            Ch* value = text;
-
-            // Skip to >
-            while (*text != Ch('>'))
-            {
-                // Determine character type
-                switch (*text)
-                {
-
-                    // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
-                    // This works for all W3C test files except for 2 most wicked
-                    case Ch('['):
-                    {
-                        ++text;     // Skip '['
-                        int depth = 1;
-
-                        while (depth > 0)
-                        {
-                            switch (*text)
-                            {
-                                case Ch('['):
-                                    ++depth;
-                                    break;
-
-                                case Ch(']'):
-                                    --depth;
-                                    break;
-
-                                case 0:
-                                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                            }
-
-                            ++text;
-                        }
-
-                        break;
-                    }
-
-                    // Error on end of text
-                    case Ch('\0'):
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-
-                    // Other character, skip it
-                    default:
-                        ++text;
-
-                }
-            }
-
-            // If DOCTYPE nodes enabled
-            if (Flags & parse_doctype_node)
-            {
-                // Create a new doctype node
-                xml_node<Ch>* doctype = this->allocate_node(node_doctype);
-                doctype->value(value, text - value);
-
-                // Place zero terminator after value
-                if (!(Flags & parse_no_string_terminators))
-                {
-                    *text = Ch('\0');
-                }
-
-                text += 1;      // skip '>'
-                return doctype;
-            }
-            else
-            {
-                text += 1;      // skip '>'
-                return nullptr;
-            }
-
-        }
-
-        // Parse PI
-        template<int Flags>
-        xml_node<Ch>* parse_pi(Ch*& text)
-        {
-            // If creation of PI nodes is enabled
-            if (Flags & parse_pi_nodes)
-            {
-                // Create pi node
-                xml_node<Ch>* pi = this->allocate_node(node_pi);
-
-                // Extract PI target name
-                Ch* name = text;
-                skip<node_name_pred, Flags>(text);
-
-                if (text == name)
-                {
-                    RAPIDXML_PARSE_ERROR("expected PI target", text);
-                }
-
-                pi->name(name, text - name);
-
-                // Skip whitespace between pi target and pi
-                skip<whitespace_pred, Flags>(text);
-
-                // Remember start of pi
-                Ch* value = text;
-
-                // Skip to '?>'
-                while (text[0] != Ch('?') || text[1] != Ch('>'))
-                {
-                    if (*text == Ch('\0'))
-                    {
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                    }
-
-                    ++text;
-                }
-
-                // Set pi value (verbatim, no entity expansion or whitespace normalization)
-                pi->value(value, text - value);
-
-                // Place zero terminator after name and value
-                if (!(Flags & parse_no_string_terminators))
-                {
-                    pi->name()[pi->name_size()] = Ch('\0');
-                    pi->value()[pi->value_size()] = Ch('\0');
-                }
-
-                text += 2;                          // Skip '?>'
-                return pi;
-            }
-            else
-            {
-                // Skip to '?>'
-                while (text[0] != Ch('?') || text[1] != Ch('>'))
-                {
-                    if (*text == Ch('\0'))
-                    {
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                    }
-
-                    ++text;
-                }
-
-                text += 2;    // Skip '?>'
-                return nullptr;
-            }
-        }
-
-        // Parse and append data
-        // Return character that ends data.
-        // This is necessary because this character might have been overwritten by a terminating 0
-        template<int Flags>
-        Ch parse_and_append_data(xml_node<Ch>* node, Ch*& text, Ch* contents_start)
-        {
-            // Backup to contents start if whitespace trimming is disabled
-            if (!(Flags & parse_trim_whitespace))
-            {
-                text = contents_start;
-            }
-
-            // Skip until end of data
-            Ch* value = text, *end;
-
-            if (Flags & parse_normalize_whitespace)
-            {
-                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
-            }
-            else
-            {
-                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
-            }
-
-            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
-            if (Flags & parse_trim_whitespace)
-            {
-                if (Flags & parse_normalize_whitespace)
-                {
-                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
-                    if (*(end - 1) == Ch(' '))
-                    {
-                        --end;
-                    }
-                }
-                else
-                {
-                    // Backup until non-whitespace character is found
-                    while (whitespace_pred::test(*(end - 1)))
-                    {
-                        --end;
-                    }
-                }
-            }
-
-            // If characters are still left between end and value (this test is only necessary if normalization is enabled)
-            // Create new data node
-            if (!(Flags & parse_no_data_nodes))
-            {
-                xml_node<Ch>* data = this->allocate_node(node_data);
-                data->value(value, end - value);
-                node->append_node(data);
-            }
-
-            // Add data to parent node if no data exists yet
-            if (!(Flags & parse_no_element_values))
-                if (*node->value() == Ch('\0'))
-                {
-                    node->value(value, end - value);
-                }
-
-            // Place zero terminator after value
-            if (!(Flags & parse_no_string_terminators))
-            {
-                Ch ch = *text;
-                *end = Ch('\0');
-                return ch;      // Return character that ends data; this is required because zero terminator overwritten it
-            }
-
-            // Return character that ends data
-            return *text;
-        }
-
-        // Parse CDATA
-        template<int Flags>
-        xml_node<Ch>* parse_cdata(Ch*& text)
-        {
-            // If CDATA is disabled
-            if (Flags & parse_no_data_nodes)
-            {
-                // Skip until end of cdata
-                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
-                {
-                    if (!text[0])
-                    {
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                    }
-
-                    ++text;
-                }
-
-                text += 3;      // Skip ]]>
-                return nullptr;       // Do not produce CDATA node
-            }
-
-            // Skip until end of cdata
-            Ch* value = text;
-
-            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
-            {
-                if (!text[0])
-                {
-                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                }
-
-                ++text;
-            }
-
-            // Create new cdata node
-            xml_node<Ch>* cdata = this->allocate_node(node_cdata);
-            cdata->value(value, text - value);
-
-            // Place zero terminator after value
-            if (!(Flags & parse_no_string_terminators))
-            {
-                *text = Ch('\0');
-            }
-
-            text += 3;      // Skip ]]>
-            return cdata;
-        }
-
-        // Parse element node
-        template<int Flags>
-        xml_node<Ch>* parse_element(Ch*& text)
-        {
-            // Create element node
-            xml_node<Ch>* element = this->allocate_node(node_element);
-
-            // Extract element name
-            Ch* name = text;
-            skip<node_name_pred, Flags>(text);
-
-            if (text == name)
-            {
-                RAPIDXML_PARSE_ERROR("expected element name", text);
-            }
-
-            element->name(name, text - name);
-
-            // Skip whitespace between element name and attributes or >
-            skip<whitespace_pred, Flags>(text);
-
-            // Parse attributes, if any
-            parse_node_attributes<Flags>(text, element);
-
-            // Determine ending type
-            if (*text == Ch('>'))
-            {
-                ++text;
-                parse_node_contents<Flags>(text, element);
-            }
-            else if (*text == Ch('/'))
-            {
-                ++text;
-
-                if (*text != Ch('>'))
-                {
-                    RAPIDXML_PARSE_ERROR("expected >", text);
-                }
-
-                ++text;
-            }
-            else
-            {
-                RAPIDXML_PARSE_ERROR("expected >", text);
-            }
-
-            // Place zero terminator after name
-            if (!(Flags & parse_no_string_terminators))
-            {
-                element->name()[element->name_size()] = Ch('\0');
-            }
-
-            // Return parsed element
-            return element;
-        }
-
-        // Determine node type, and parse it
-        template<int Flags>
-        xml_node<Ch>* parse_node(Ch*& text)
-        {
-            // Parse proper node type
-            switch (text[0])
-            {
-
-                // <...
-                default:
-                    // Parse and append element node
-                    return parse_element<Flags>(text);
-
-                // <?...
-                case Ch('?'):
-                    ++text;     // Skip ?
-
-                    if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
-                        (text[1] == Ch('m') || text[1] == Ch('M')) &&
-                        (text[2] == Ch('l') || text[2] == Ch('L')) &&
-                        whitespace_pred::test(text[3]))
-                    {
-                        // '<?xml ' - xml declaration
-                        text += 4;      // Skip 'xml '
-                        return parse_xml_declaration<Flags>(text);
-                    }
-                    else
-                    {
-                        // Parse PI
-                        return parse_pi<Flags>(text);
-                    }
-
-                // <!...
-                case Ch('!'):
-
-                    // Parse proper subset of <! node
-                    switch (text[1])
-                    {
-
-                        // <!-
-                        case Ch('-'):
-                            if (text[2] == Ch('-'))
-                            {
-                                // '<!--' - xml comment
-                                text += 3;     // Skip '!--'
-                                return parse_comment<Flags>(text);
-                            }
-
-                            break;
-
-                        // <![
-                        case Ch('['):
-                            if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
-                                text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
-                            {
-                                // '<![CDATA[' - cdata
-                                text += 8;     // Skip '![CDATA['
-                                return parse_cdata<Flags>(text);
-                            }
-
-                            break;
-
-                        // <!D
-                        case Ch('D'):
-                            if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
-                                text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
-                                whitespace_pred::test(text[8]))
-                            {
-                                // '<!DOCTYPE ' - doctype
-                                text += 9;      // skip '!DOCTYPE '
-                                return parse_doctype<Flags>(text);
-                            }
-
-                    }   // switch
-
-                    // Attempt to skip other, unrecognized node types starting with <!
-                    ++text;     // Skip !
-
-                    while (*text != Ch('>'))
-                    {
-                        if (*text == 0)
-                        {
-                            RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-                        }
-
-                        ++text;
-                    }
-
-                    ++text;     // Skip '>'
-                    return nullptr;   // No node recognized
-
-            }
-        }
-
-        // Parse contents of the node - children, data etc.
-        template<int Flags>
-        void parse_node_contents(Ch*& text, xml_node<Ch>* node)
-        {
-            // For all children and text
-            while (1)
-            {
-                // Skip whitespace between > and node contents
-                Ch* contents_start = text;      // Store start of node contents before whitespace is skipped
-                skip<whitespace_pred, Flags>(text);
-                Ch next_char = *text;
-
-                // After data nodes, instead of continuing the loop, control jumps here.
-                // This is because zero termination inside parse_and_append_data() function
-                // would wreak havoc with the above code.
-                // Also, skipping whitespace after data nodes is unnecessary.
-after_data_node:
-
-                // Determine what comes next: node closing, child node, data node, or 0?
-                switch (next_char)
-                {
-
-                    // Node closing or child node
-                    case Ch('<'):
-                        if (text[1] == Ch('/'))
-                        {
-                            // Node closing
-                            text += 2;      // Skip '</'
-
-                            if (Flags & parse_validate_closing_tags)
-                            {
-                                // Skip and validate closing tag name
-                                Ch* closing_name = text;
-                                skip<node_name_pred, Flags>(text);
-
-                                if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
-                                {
-                                    RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
-                                }
-                            }
-                            else
-                            {
-                                // No validation, just skip name
-                                skip<node_name_pred, Flags>(text);
-                            }
-
-                            // Skip remaining whitespace after node name
-                            skip<whitespace_pred, Flags>(text);
-
-                            if (*text != Ch('>'))
-                            {
-                                RAPIDXML_PARSE_ERROR("expected >", text);
-                            }
-
-                            ++text;     // Skip '>'
-                            return;     // Node closed, finished parsing contents
-                        }
-                        else
-                        {
-                            // Child node
-                            ++text;     // Skip '<'
-
-                            if (xml_node<Ch>* child = parse_node<Flags>(text))
-                            {
-                                node->append_node(child);
-                            }
-                        }
-
-                        break;
-
-                    // End of data - error
-                    case Ch('\0'):
-                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
-
-                    // Data node
-                    default:
-                        next_char = parse_and_append_data<Flags>(node, text, contents_start);
-                        goto after_data_node;   // Bypass regular processing after data nodes
-
-                }
-            }
-        }
-
-        // Parse XML attributes of the node
-        template<int Flags>
-        void parse_node_attributes(Ch*& text, xml_node<Ch>* node)
-        {
-            // For all attributes
-            while (attribute_name_pred::test(*text))
-            {
-                // Extract attribute name
-                Ch* name = text;
-                ++text;     // Skip first character of attribute name
-                skip<attribute_name_pred, Flags>(text);
-
-                if (text == name)
-                {
-                    RAPIDXML_PARSE_ERROR("expected attribute name", name);
-                }
-
-                // Create new attribute
-                xml_attribute<Ch>* attribute = this->allocate_attribute();
-                attribute->name(name, text - name);
-                node->append_attribute(attribute);
-
-                // Skip whitespace after attribute name
-                skip<whitespace_pred, Flags>(text);
-
-                // Skip =
-                if (*text != Ch('='))
-                {
-                    RAPIDXML_PARSE_ERROR("expected =", text);
-                }
-
-                ++text;
-
-                // Add terminating zero after name
-                if (!(Flags & parse_no_string_terminators))
-                {
-                    attribute->name()[attribute->name_size()] = 0;
-                }
-
-                // Skip whitespace after =
-                skip<whitespace_pred, Flags>(text);
-
-                // Skip quote and remember if it was ' or "
-                Ch quote = *text;
-
-                if (quote != Ch('\'') && quote != Ch('"'))
-                {
-                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
-                }
-
-                ++text;
-
-                // Extract attribute value and expand char refs in it
-                Ch* value = text, *end;
-                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
-
-                if (quote == Ch('\''))
-                {
-                    end = skip_and_expand_character_refs < attribute_value_pred < Ch('\'') >, attribute_value_pure_pred < Ch('\'') >, AttFlags > (text);
-                }
-                else
-                {
-                    end = skip_and_expand_character_refs < attribute_value_pred < Ch('"') >, attribute_value_pure_pred < Ch('"') >, AttFlags > (text);
-                }
-
-                // Set attribute value
-                attribute->value(value, end - value);
-
-                // Make sure that end quote is present
-                if (*text != quote)
-                {
-                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
-                }
-
-                ++text;     // Skip quote
-
-                // Add terminating zero after value
-                if (!(Flags & parse_no_string_terminators))
-                {
-                    attribute->value()[attribute->value_size()] = 0;
-                }
-
-                // Skip whitespace after attribute value
-                skip<whitespace_pred, Flags>(text);
-            }
-        }
-
-    };
-
-    //! \cond internal
-    namespace internal
-    {
-
-        // Whitespace (space \n \r \t)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
-            1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
-            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
-        };
-
-        // Node name (anything but space \n \r \t / > ? \0)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Text (i.e. PCDATA) (anything but < \0)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_text[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
-        // (anything but < \0 &)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
-        // (anything but < \0 & space \n \r \t)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Attribute name (anything but space \n \r \t / < > = ? ! \0)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Attribute data with single quote (anything but ' \0)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Attribute data with single quote that does not require processing (anything but ' \0 &)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Attribute data with double quote (anything but " \0)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Attribute data with double quote that does not require processing (anything but " \0 &)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
-            1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
-            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
-        };
-
-        // Digits (dec and hex, 255 denotes end of numeric character reference)
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
-        {
-            // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 1
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 2
-            0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 255, 255, 255, 255, 255, 255, // 3
-            255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 4
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 5
-            255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 6
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 7
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 8
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 9
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // A
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // B
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // C
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // D
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // E
-            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 // F
-        };
-
-        // Upper case conversion
-        template<int Dummy>
-        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
-        {
-            // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
-            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
-            16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
-            32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
-            48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
-            64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
-            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
-            96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
-            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, // 7
-            128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 8
-            144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 9
-            160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // A
-            176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // B
-            192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // C
-            208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // D
-            224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // E
-            240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // F
-        };
-    }
-    //! \endcond
-
-}
-
-// Undefine internal macros
-#undef RAPIDXML_PARSE_ERROR
-
-// On MSVC, restore warnings state
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#endif /*__RAPIDXML_H_INCLUDE__*/
+#include "SimoxUtility/xml/rapidxml/rapidxml.hpp"