tinyxml_interface.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "tinyxml_interface.hpp"
27 
28 namespace casadi {
29 
30 extern "C"
31 int CASADI_XMLFILE_TINYXML_EXPORT
32 casadi_register_xmlfile_tinyxml(XmlFileInternal::Plugin* plugin) {
33  plugin->creator = TinyXmlInterface::creator;
34  plugin->name = "tinyxml";
35  plugin->doc = TinyXmlInterface::meta_doc.c_str();
36  plugin->version = CASADI_VERSION;
37  return 0;
38 }
39 
40 extern "C"
41 void CASADI_XMLFILE_TINYXML_EXPORT casadi_load_xmlfile_tinyxml() {
43 }
44 
46 }
47 
49 }
50 
52  // Load XML file from disk
53  XMLError err = doc_.LoadFile(filename.c_str());
54  casadi_assert(!err, "Cannot load " + filename);
55  // Import to CasADi representation
56  XmlNode n;
57  try {
58  n = import_node(&doc_);
59  } catch (std::exception& e) {
60  casadi_error("Cannot import " + filename + ": " + std::string(e.what()));
61  }
62  return n;
63 }
64 
65 void TinyXmlInterface::dump(const std::string& filename, const XmlNode& node) {
66  // Add encoding declaration
67  doc_.InsertEndChild(doc_.NewDeclaration());
68  // Export from CasADi representation
69  try {
70  export_node(&doc_, node);
71  } catch (std::exception& e) {
72  casadi_error("Cannot export " + filename + ": " + std::string(e.what()));
73  }
74  // Save XML file to disk
75  XMLError err = doc_.SaveFile(filename.c_str());
76  casadi_assert(!err, "Cannot save " + filename);
77 }
78 
80  if (!n) casadi_error("Node is 0");
81  XmlNode ret;
82 
83  ret.line = n->GetLineNum();
84 
85  // Save name
86  if (n->Value()) {
87  ret.name = n->Value();
88  }
89 
90  // Save attributes
91  if (n->ToElement()) {
92  for (const TiXmlAttribute* pAttrib=n->ToElement()->FirstAttribute();
93  pAttrib; pAttrib=pAttrib->Next()) {
94  ret.set_attribute(pAttrib->Name(), pAttrib->Value());
95  }
96  } else if (n->ToDocument()) {
97  // do nothing
98  } else {
99  casadi_error("TinyXmlInterface::import_node");
100  }
101 
102  // Count the number of children
103  casadi_int num_children = 0;
104  for (TiXmlNode* child = n->FirstChild(); child != nullptr; child = child->NextSibling()) {
105  num_children++;
106  }
107  ret.children.reserve(num_children);
108 
109  // add children
110  for (TiXmlNode* child = n->FirstChild(); child != nullptr; child = child->NextSibling()) {
111  if (child->ToElement()) {
112  ret.children.push_back(import_node(child));
113  } else if (child->ToComment()) {
114  ret.comment = child->Value();
115  } else if (child->ToText()) {
116  ret.text = child->ToText()->Value();
117  } else if (child->ToDeclaration()) {
118  // pass
119  } else if (child->ToDocument()) {
120  // pass
121  } else {
122  casadi_error("Unknown node type");
123  }
124  }
125 
126  // Note: Return value optimization
127  return ret;
128 }
129 
130 void TinyXmlInterface::export_node(TiXmlNode* n, const XmlNode& node) {
131  // Loop over children
132  for (const XmlNode& c : node.children) {
133  // Create new node for the child
134  TiXmlElement* tc = doc_.NewElement(c.name.c_str());
135  n->InsertEndChild(tc);
136  // Save all attributes
137  for (auto&& a : c.attributes) {
138  tc->SetAttribute(a.first.c_str(), a.second.c_str());
139  }
140  // Add (grand)children, if any
141  export_node(tc, c);
142  }
143 }
144 
145 
146 } // namespace casadi
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
XmlNode import_node(TiXmlNode *n)
void dump(const std::string &filename, const XmlNode &node) override
void export_node(TiXmlNode *n, const XmlNode &node)
XmlNode parse(const std::string &filename) override
TiXmlDocument doc_
XML file.
static const std::string meta_doc
A documentation string.
static XmlFileInternal * creator()
Create a new XmlFile.
The casadi namespace.
Definition: archiver.cpp:28
void CASADI_XMLFILE_TINYXML_EXPORT casadi_load_xmlfile_tinyxml()
int CASADI_XMLFILE_TINYXML_EXPORT casadi_register_xmlfile_tinyxml(XmlFileInternal::Plugin *plugin)
std::string filename(const std::string &path)
Definition: ghc.cpp:55
void set_attribute(const std::string &att_name, const std::string &att)
Add an attribute.
Definition: xml_node.cpp:60
casadi_int line
Definition: xml_node.hpp:53
std::vector< XmlNode > children
Definition: xml_node.hpp:44
std::string comment
Definition: xml_node.hpp:50
std::string text
Definition: xml_node.hpp:56
std::map< std::string, std::string > attributes
Definition: xml_node.hpp:41
std::string name
Definition: xml_node.hpp:47