xerces/Writer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file Writer.cpp
22 
23  \brief A class that models a XML writer object built on top of Xerces-C++.
24 */
25 
26 // TerraLib
27 #include "../common/Exception.h"
28 #include "../common/StringUtils.h"
29 #include "../core/encoding/CharEncoding.h"
30 #include "../core/translator/Translator.h"
31 #include "StrToXMLCh.h"
32 #include "XMLChToStr.h"
33 #include "Writer.h"
34 
35 // STL
36 #include <fstream>
37 
38 // Boost
39 #include <boost/lexical_cast.hpp>
40 
41 // Xerces-C++
42 #include <xercesc/dom/DOMDocument.hpp>
43 #include <xercesc/dom/DOMDocumentType.hpp>
44 #include <xercesc/dom/DOMElement.hpp>
45 #include <xercesc/dom/DOMException.hpp>
46 #include <xercesc/dom/DOMImplementation.hpp>
47 #include <xercesc/dom/DOMImplementationRegistry.hpp>
48 #include <xercesc/dom/DOMText.hpp>
49 
50 #include <xercesc/util/PlatformUtils.hpp>
51 #include <xercesc/util/OutOfMemoryException.hpp>
52 #include <xercesc/dom/DOM.hpp>
53 #include <xercesc/framework/StdOutFormatTarget.hpp>
54 #include <xercesc/framework/LocalFileFormatTarget.hpp>
55 #include <xercesc/framework/MemBufFormatTarget.hpp>
56 
58  : m_impl(nullptr),
59  m_doc(nullptr),
60  m_indice(0),
61  m_topIndice(0)
62 {
63  // TODO
64 }
65 
67 {
68  if(m_doc)
69  {
70  m_doc->release();
71  }
72 }
73 
74 void te::xerces::Writer::writeStartDocument(const std::string& encoding, const std::string& standalone)
75 {
76  m_standalone = te::common::Convert2UCase(standalone) == "NO" ? false : true;
77  m_encoding = encoding;
78 }
79 
81 {
82  // primeiro a declaracao dos objetos Xerces
83 #if XERCES_VERSION_MAJOR == 2
84  xercesc::DOMWriter* theSerializer = ( (xercesc::DOMImplementationLS*)m_impl)->createDOMWriter();
85  int* theOutput = 0; // for compat
86 #else // Xerces3
87  xercesc::DOMLSSerializer* theSerializer = ((xercesc::DOMImplementationLS*)m_impl)->createLSSerializer();
88  xercesc::DOMLSOutput* theOutput = nullptr;
89 #endif
90 
91  xercesc::XMLFormatTarget* myFormTarget = nullptr;
92  try
93  {
94  // Se nao tem filename, eh stdout
95  if( m_uri.empty() )
96  myFormTarget = new xercesc::StdOutFormatTarget();
97  else
98  myFormTarget = new xercesc::MemBufFormatTarget();
99 
100 #if XERCES_VERSION_MAJOR == 2
101  theSerializer->writeNode( myFormTarget, *doc_ );
102 #else // Xerces3
103  theOutput = ( (xercesc::DOMImplementationLS*)m_impl)->createLSOutput();
104  theOutput->setByteStream(myFormTarget);
105  theSerializer->write(m_doc, theOutput );
106  std::string xmlstring = (char*)((xercesc::MemBufFormatTarget*)myFormTarget)->getRawBuffer();
107  std::ofstream out(te::core::CharEncoding::fromUTF8(m_uri).c_str());
108  out << xmlstring;
109  out.close();
110 #endif
111  delete theOutput;
112  delete theSerializer;
113  delete myFormTarget;
114  }
115  catch( const xercesc::OutOfMemoryException& )
116  {
117  delete theOutput;
118  delete theSerializer;
119  delete myFormTarget;
120 
121  throw te::common::Exception(TE_TR("Out of memory"));
122  }
123  catch( const xercesc::DOMException& e )
124  {
125  delete theOutput;
126  delete theSerializer;
127  delete myFormTarget;
128 
129  std::string err = XMLChToStr(e.getMessage()).getStr();
130 
131  throw te::common::Exception(TE_TR("Exception message is: ") + err);
132  }
133  catch(...)
134  {
135  delete theSerializer;
136  delete myFormTarget;
137 
138  throw te::common::Exception(TE_TR("An error occurred while outputing the xml document."));
139  }
140 }
141 
142 void te::xerces::Writer::writeStartElement(const std::string& qName)
143 {
144  try
145  {
146  if(!m_doc)
147  {
148  m_impl = xercesc::DOMImplementationRegistry::getDOMImplementation(StrToXMLCh("Core").getXMLCh());
149 
150  if(m_impl)
151  {
152  try
153  {
154  if(m_rootNamespaceUri.empty())
155  m_doc = m_impl->createDocument(nullptr, StrToXMLCh(qName).getXMLCh(), nullptr);
156  else
157  m_doc = m_impl->createDocument(StrToXMLCh(m_rootNamespaceUri).getXMLCh(), StrToXMLCh(qName).getXMLCh(), nullptr);
158 
159  m_doc->setXmlStandalone(m_standalone);
160 
161  m_elementSet.push_back(m_doc->getDocumentElement());
162 
163  m_topIndice = 0;
164 
165  m_topElementSet.push_back(0);
166  }
167  catch(xercesc::DOMException& e)
168  {
169  std::string err = XMLChToStr(e.getMessage()).getStr();
170  }
171  }
172  else
173  throw te::common::Exception(TE_TR("DOM implementation fails"));
174  }
175  else
176  {
177  m_elementSet.push_back(m_doc->createElement(StrToXMLCh(qName).getXMLCh()));
178  m_elementSet[m_topIndice]->appendChild(m_elementSet[++m_indice] );
179 
180  // ajusta o topElement do Elemento atual
181  m_topElementSet.push_back(m_topIndice);
182 
183  // ele vira pai
185  }
186  }
187  catch( const xercesc::OutOfMemoryException& )
188  {
189  throw te::common::Exception(TE_TR("Out of memory"));
190  }
191  catch( const xercesc::DOMException& e )
192  {
193  std::string err = XMLChToStr(e.getMessage()).getStr();
194  throw te::common::Exception(TE_TR("Exception message is: ") + err );
195  }
196  catch(...)
197  {
198  throw te::common::Exception(TE_TR("An error occurred adding a element"));
199  }
200 }
201 
202 void te::xerces::Writer::writeElement(const std::string& qName, const std::string& value)
203 {
204  try
205  {
206  m_elementSet.push_back(m_doc->createElement(StrToXMLCh(qName).getXMLCh()));
207  m_elementSet[m_topIndice]->appendChild(m_elementSet[++m_indice]);
208 
209  // ajusta o topElement do Elemento atual
210  m_topElementSet.push_back(m_topIndice);
211 
212  // Colocando dados no elemento, se houver
213  if(!value.empty())
214  addText(value);
215  }
216  catch(const xercesc::DOMException& e)
217  {
218  throw te::common::Exception(TE_TR("Exception message is: ") + XMLChToStr(e.getMessage()).getStr());
219  }
220  catch(...)
221  {
222  throw te::common::Exception(TE_TR("An error occurred adding the element: ") + ( qName.empty() ? std::string( "[empty]" ) : qName ));
223  }
224 }
225 
226 void te::xerces::Writer::writeElement(const std::string& qName, const double& value)
227 {
228  writeElement(qName, boost::lexical_cast<std::string>(value));
229 }
230 
231 void te::xerces::Writer::writeElement(const std::string& qName, boost::int32_t value)
232 {
233  writeElement(qName, boost::lexical_cast<std::string>(value));
234 }
235 
236 void te::xerces::Writer::writeElement(const std::string& qName, boost::uint32_t value)
237 {
238  writeElement(qName, boost::lexical_cast<std::string>(value));
239 }
240 
241 void te::xerces::Writer::writeElement(const std::string& qName, boost::int64_t value)
242 {
243  writeElement(qName, boost::lexical_cast<std::string>(value));
244 }
245 
246 void te::xerces::Writer::writeElement(const std::string& qName, boost::uint64_t value)
247 {
248  writeElement(qName, boost::lexical_cast<std::string>(value));
249 }
250 
251 void te::xerces::Writer::writeAttribute(const std::string& attName, const std::string& value)
252 {
253  try
254  {
255  m_elementSet[m_topIndice]->setAttribute(StrToXMLCh(attName).getXMLCh(), StrToXMLCh(value).getXMLCh());
256  }
257  catch(const xercesc::DOMException& e)
258  {
259  throw te::common::Exception(TE_TR("Exception message is: ") + XMLChToStr(e.getMessage()).getStr());
260  }
261  catch(...)
262  {
263  throw te::common::Exception(TE_TR("An error occurred adding the attribute: ") + ( attName.empty() ? std::string( "[empty]" ) : attName ));
264  }
265 }
266 
267 void te::xerces::Writer::writeAttribute(const std::string& attName, const double& value)
268 {
269  writeAttribute(attName, boost::lexical_cast<std::string>(value));
270 }
271 
272 void te::xerces::Writer::writeAttribute(const std::string& attName, boost::int32_t value)
273 {
274  writeAttribute(attName, boost::lexical_cast<std::string>(value));
275 }
276 
277 void te::xerces::Writer::writeAttribute(const std::string& attName, boost::uint32_t value)
278 {
279  writeAttribute(attName, boost::lexical_cast<std::string>(value));
280 }
281 
282 void te::xerces::Writer::writeAttribute(const std::string& attName, boost::int64_t value)
283 {
284  writeAttribute(attName, boost::lexical_cast<std::string>(value));
285 }
286 
287 void te::xerces::Writer::writeAttribute(const std::string& attName, boost::uint64_t value)
288 {
289  writeAttribute(attName, boost::lexical_cast<std::string>(value));
290 }
291 
292 void te::xerces::Writer::writeValue(const std::string& value)
293 {
294  addText(value);
295 }
296 
297 void te::xerces::Writer::writeValue(const double& value)
298 {
299  addText(boost::lexical_cast<std::string>(value));
300 }
301 
302 void te::xerces::Writer::writeValue(boost::int32_t value)
303 {
304  addText(boost::lexical_cast<std::string>(value));
305 }
306 
307 void te::xerces::Writer::writeValue(boost::uint32_t value)
308 {
309  addText(boost::lexical_cast<std::string>(value));
310 }
311 
312 void te::xerces::Writer::writeValue(boost::int64_t value)
313 {
314  addText(boost::lexical_cast<std::string>(value));
315 }
316 
317 void te::xerces::Writer::writeValue(boost::uint64_t value)
318 {
319  addText(boost::lexical_cast<std::string>(value));
320 }
321 
322 void te::xerces::Writer::writeEndElement(const std::string& /*qName*/)
323 {
325 }
326 
327 void te::xerces::Writer::addText(const std::string& qValue)
328 {
329  try
330  {
331  xercesc::DOMText* domText = m_doc->createTextNode(StrToXMLCh(qValue).getXMLCh());
332  m_elementSet[m_indice]->appendChild(domText);
333  }
334  catch(const xercesc::DOMException& e)
335  {
336  throw te::common::Exception(TE_TR("Exception message is: ") + XMLChToStr(e.getMessage()).getStr());
337  }
338  catch(...)
339  {
340  throw te::common::Exception(TE_TR("An error occurred adding the value to the element"));
341  }
342 }
std::string m_rootNamespaceUri
A class for converting a standard string to a Xerces string (XMLCh).
Definition: StrToXMLCh.h:47
std::size_t m_indice
Index to build the ElementSet vector.
void writeStartElement(const std::string &qName)
std::vector< std::size_t > m_topElementSet
This vector gives the parent node of each element.
A class for converting a standard string to a Xerces string (XMLCh).
void addText(const std::string &qValue)
Adds a XML value to the last inserted element.
void writeStartDocument(const std::string &encoding, const std::string &standalone)
std::string Convert2UCase(const std::string &value)
It converts a string to upper case.
Definition: StringUtils.h:168
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
static std::string fromUTF8(const std::string &src)
Convert a string in UTF-8 to the current locale encoding.
void writeElement(const std::string &qName, const std::string &value)
A class for converting a Xerces string (XMLCh) to a standard string.
Definition: XMLChToStr.h:50
A class for converting a Xerces string (XMLCh) to a standard string.
~Writer()
Destructor.
std::vector< XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * > m_elementSet
Vector that contains all the elements (nodes).
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
std::size_t m_topIndice
Index of the parent node.
XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementation * m_impl
DOM element - implementation.
Writer()
Default constructor.
void writeEndElement(const std::string &qName)
std::string m_encoding
void writeValue(const std::string &value)
void writeAttribute(const std::string &attName, const std::string &value)
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * m_doc
DOM element - document.