source: rrlib_xml/tDocument.cpp

tip
Last change on this file was 69:b9bd564ea70c, checked in by Max Reichardt <mreichardt@…>, 2 years ago

Fixes compiler warnings that appear with additional non-default warning options enabled

File size: 8.7 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/xml/tDocument.cpp
23 *
24 * \author  Tobias Foehst
25 *
26 * \date    2010-06-24
27 *
28 */
29//----------------------------------------------------------------------
30#include "rrlib/xml/tDocument.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include <iostream>
36#include <memory>
37
38extern "C"
39{
40#include <libxml/xpath.h>
41}
42
43//----------------------------------------------------------------------
44// Internal includes with ""
45//----------------------------------------------------------------------
46#include "rrlib/xml/tException.h"
47#include "rrlib/xml/tCleanupHandler.h"
48
49//----------------------------------------------------------------------
50// Debugging
51//----------------------------------------------------------------------
52#include <cassert>
53
54//----------------------------------------------------------------------
55// Namespace usage
56//----------------------------------------------------------------------
57
58//----------------------------------------------------------------------
59// Namespace declaration
60//----------------------------------------------------------------------
61namespace rrlib
62{
63namespace xml
64{
65
66//----------------------------------------------------------------------
67// Forward declarations / typedefs / enums
68//----------------------------------------------------------------------
69
70//----------------------------------------------------------------------
71// Const values
72//----------------------------------------------------------------------
73
74//----------------------------------------------------------------------
75// Implementation
76//----------------------------------------------------------------------
77
78//----------------------------------------------------------------------
79// tDocument constructors
80//----------------------------------------------------------------------
81tDocument::tDocument()
82  : document(xmlNewDoc(reinterpret_cast<const xmlChar *>("1.0"))),
83    root_node(0)
84{
85  assert(this->document);
86  tCleanupHandler::Instance();
87}
88
89tDocument::tDocument(const std::string &file_name, bool validate)
90  : document(xmlReadFile(file_name.c_str(), 0, validate ? XML_PARSE_DTDVALID : 0)),
91    root_node(reinterpret_cast<tNode *>(xmlDocGetRootElement(this->document)))
92{
93  this->CheckIfDocumentIsValid("Could not parse XML file `" + file_name + "'!");
94  tCleanupHandler::Instance();
95}
96
97tDocument::tDocument(const std::string &file_name, const std::string &encoding, bool validate)
98  : document(xmlReadFile(file_name.c_str(), encoding.c_str(), validate ? XML_PARSE_DTDVALID : 0)),
99    root_node(reinterpret_cast<tNode *>(xmlDocGetRootElement(this->document)))
100{
101  this->CheckIfDocumentIsValid("Could not parse XML file `" + file_name + "'!");
102  tCleanupHandler::Instance();
103}
104
105tDocument::tDocument(const void *buffer, size_t size, bool validate)
106  : document(xmlReadMemory(reinterpret_cast<const char *>(buffer), size, "noname.xml", 0, validate ? XML_PARSE_DTDVALID : 0)),
107    root_node(reinterpret_cast<tNode *>(xmlDocGetRootElement(this->document)))
108{
109  this->CheckIfDocumentIsValid("Could not parse XML from memory buffer `" + std::string(reinterpret_cast<const char *>(buffer)) + "'!");
110  tCleanupHandler::Instance();
111}
112
113tDocument::tDocument(const void *buffer, size_t size, const std::string &encoding, bool validate)
114  : document(xmlReadMemory(reinterpret_cast<const char *>(buffer), size, "noname.xml", encoding.c_str(), validate ? XML_PARSE_DTDVALID : 0)),
115    root_node(reinterpret_cast<tNode *>(xmlDocGetRootElement(this->document)))
116{
117  this->CheckIfDocumentIsValid("Could not parse XML from memory buffer `" + std::string(reinterpret_cast<const char *>(buffer)) + "'!");
118  tCleanupHandler::Instance();
119}
120
121tDocument::tDocument(tDocument && other)
122  : document(0),
123    root_node(0)
124{
125  std::swap(document, other.document);
126  std::swap(root_node, other.root_node);
127}
128
129//----------------------------------------------------------------------
130// tDocument destructor
131//----------------------------------------------------------------------
132tDocument::~tDocument()
133{
134  if (this->document)
135  {
136    xmlFreeDoc(this->document);
137  }
138}
139
140//----------------------------------------------------------------------
141// tDocument operator =
142//----------------------------------------------------------------------
143tDocument &tDocument::operator = (const tDocument & other)
144{
145  if (this == &other)
146  {
147    return *this;
148  }
149  xmlFreeDoc(this->document);
150  this->document = xmlCopyDoc(other.document, true);
151  this->root_node = reinterpret_cast<tNode *>(xmlDocGetRootElement(this->document));
152  return *this;
153}
154
155//----------------------------------------------------------------------
156// tDocument RootNode
157//----------------------------------------------------------------------
158tNode &tDocument::RootNode()
159{
160  if (!this->root_node)
161  {
162    throw tException("No root node defined for this document!");
163  }
164  return *this->root_node;
165}
166
167//----------------------------------------------------------------------
168// tDocument AddRootNode
169//----------------------------------------------------------------------
170tNode &tDocument::AddRootNode(const std::string &name)
171{
172  if (this->root_node)
173  {
174    throw tException("Root node already exists with name `" + name + "'!");
175  }
176  this->root_node = reinterpret_cast<tNode *>(xmlNewNode(0, reinterpret_cast<const xmlChar *>(name.c_str())));
177  xmlDocSetRootElement(this->document, this->root_node);
178  return *this->root_node;
179}
180
181//----------------------------------------------------------------------
182// tDocument FindNode
183//----------------------------------------------------------------------
184const tNode &tDocument::FindNode(const std::string &name) const
185{
186  auto cleanup_path_context = [](xmlXPathContext * ptr)
187  {
188    xmlXPathFreeContext(ptr);
189  }; // clean up the XPath context
190  std::unique_ptr<xmlXPathContext, decltype(cleanup_path_context)> xpath_context(xmlXPathNewContext(this->document), cleanup_path_context); // create and initialize an XPath context for this document with auto cleanup
191
192  if (xpath_context == nullptr)
193  {
194    throw tException("Could not create the XPath context!");
195  }
196
197  auto cleanup_path_object = [](xmlXPathObject * ptr)
198  {
199    xmlXPathFreeObject(ptr);
200  }; // clean up the XPath object
201  std::unique_ptr<xmlXPathObject, decltype(cleanup_path_object)> xpath_object(xmlXPathEvalExpression(reinterpret_cast<xmlChar*>(const_cast<char*>(name.c_str())), xpath_context.get()), cleanup_path_object); // create and initialize an XPath object as query result with auto cleanup
202
203  if (xpath_object == nullptr)
204  {
205    throw tException("Could not evaluate the XPath expression!");
206  }
207
208  if ((xpath_object->nodesetval == nullptr) || (xpath_object->nodesetval->nodeTab == nullptr))
209  {
210    throw tException("Could not find the expected node!");
211  }
212  xmlNode *node = xpath_object->nodesetval->nodeTab[0]; // fetch node from query result
213  return *reinterpret_cast<tNode *>(node);
214}
215
216//----------------------------------------------------------------------
217// tDocument WriteToFile
218//----------------------------------------------------------------------
219void tDocument::WriteToFile(const std::string &file_name, int compression) const
220{
221  if (compression)
222  {
223    xmlSetDocCompressMode(this->document, compression);
224  }
225  xmlSaveFormatFileEnc(file_name.c_str(), this->document, "UTF-8", 1);
226}
227
228//----------------------------------------------------------------------
229// tDocument CheckIfDocumentIsValid
230//----------------------------------------------------------------------
231void tDocument::CheckIfDocumentIsValid(const std::string &exception_message)
232{
233  if (!this->document)
234  {
235    throw tException(exception_message);
236  }
237}
238
239//----------------------------------------------------------------------
240// End of namespace declaration
241//----------------------------------------------------------------------
242}
243}
Note: See TracBrowser for help on using the repository browser.