XmlElement.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright 2007, 2008, 2009, 2010, 2011 Instituto de Sistemas e Robotica, Instituto Superior Tecnico
00003 
00004 This file is part of MeRMaID.
00005 
00006 MeRMaID is free software: you can redistribute it and/or modify
00007 it under the terms of the GNU Lesser General Public License as published by
00008 the Free Software Foundation, either version 3 of the License, or
00009 (at your option) any later version.
00010 
00011 MeRMaID is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public License
00017 along with MeRMaID.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 
00021 
00022 /**
00023  * @Filename XmlElement.cpp
00024  * @Description Implementation of the XmlElement class
00025  * @Status Implementing
00026  * @Version $Id: XmlElement.cpp 1 2011-03-04 18:13:18Z jreis $
00027  * @Maintainer Nelson Ramos (nmsra@mega.ist.utl.pt)
00028  */
00029 
00030 #include "config.h"
00031 
00032 #include "XmlElement.hpp"
00033 
00034 #include <string>
00035 #include <sstream>
00036 
00037 #include <libxml/xmlmemory.h>
00038 #include <libxml/parser.h>
00039 
00040 #include <Exception.hpp>
00041 
00042 #include "XmlItem.hpp"
00043 
00044 using namespace mermaid::support::xml;
00045 using std::string;
00046 using std::stringstream;
00047 using mermaid::support::errorhandling::Exception;
00048 
00049 
00050 
00051 XmlElement::XmlElement()
00052 {
00053   name_ = string ("UNNAMED");
00054   charData_ = XmlCharDataVector();
00055   childrenElements_ = XmlElementVector();
00056   attributes_ = XmlAttributeVector();
00057   items_ = XmlItemVector();
00058 }
00059 
00060 
00061 
00062 XmlElement::XmlElement (const XmlElement& e)
00063 {
00064   copyFrom (e);
00065 }
00066 
00067 
00068 
00069 XmlElement::XmlElement (string xml)
00070 {
00071   xmlNodePtr rootElementNode;
00072   
00073   xmlParserCtxtPtr parserCtxtPtr = xmlNewParserCtxt();
00074   xmlDocPtr docPtr = xmlCtxtReadMemory (parserCtxtPtr,
00075                                         xml.data(),
00076                                         xml.size(),
00077                                         NULL,
00078                                         NULL,
00079                                         0);
00080                                         
00081   if ( (parserCtxtPtr->wellFormed == 0) || (docPtr == NULL)) {
00082     XmlElement();
00083     throw Exception ("XmlElement::XmlElement(string xml) : unable to "
00084                      "build from string: \"" + xml + "\"");
00085   }
00086   
00087   rootElementNode = xmlDocGetRootElement (docPtr);
00088   
00089   if (rootElementNode == NULL) {
00090     xmlFreeDoc (docPtr);
00091     XmlElement();
00092     throw Exception ("XmlElement::XmlElement(string xml) : unable to "
00093                      "build from string: \"" + xml + "\"");
00094   }
00095   this->buildFromLibxml2Node (rootElementNode);
00096   
00097   if (parserCtxtPtr != NULL) {
00098     xmlFreeParserCtxt (parserCtxtPtr);
00099   }
00100   
00101   if (docPtr != NULL) {
00102     xmlFreeDoc (docPtr);
00103   }
00104 }
00105 
00106 
00107 
00108 XmlElement::XmlElement (xmlNodePtr node)
00109 {
00110   this->buildFromLibxml2Node (node);
00111 }
00112 
00113 
00114 
00115 void XmlElement::buildFromLibxml2Node (xmlNodePtr node)
00116 {
00117   // read name
00118   name_ = string ( (char*) node->name);
00119   
00120   // get all children items
00121   xmlNodePtr child = node->children;
00122   while (child != NULL) {
00123     if (child->type == XML_ELEMENT_NODE) {
00124       shared_ptr<XmlElement> e =
00125         shared_ptr<XmlElement> (new XmlElement (child));
00126       if (e == false) {
00127         throw Exception ("XmlElement::buildFromLibxml2Node : unable to "
00128                          "create XmlElement");
00129       }
00130       childrenElements_.push_back (e);
00131       items_.push_back (static_cast<XmlItem*> (e.get()));
00132       //! @todo remove dereferencing of shared_ptr
00133     }
00134     else if ( (child->type == XML_TEXT_NODE)
00135               || (child->type == XML_CDATA_SECTION_NODE)) {
00136       shared_ptr<XmlCharData> c =
00137         shared_ptr<XmlCharData> (new XmlCharData ( (char*) child->content));
00138       if (c == false) {
00139         throw Exception ("XmlElement::buildFromLibxml2Node : unable to "
00140                          "create XmlCharData");
00141       }
00142       charData_.push_back (c);
00143       items_.push_back (static_cast<XmlItem*> (c.get()));
00144       //! @todo remove dereferencing of shared_ptr
00145     }
00146     child = child->next;
00147   }
00148   
00149   // get all attributes
00150   xmlAttrPtr attr = node->properties;
00151   while ( (attr != NULL)) {
00152     if (attr->type == XML_ATTRIBUTE_NODE) {
00153       attributes_.push_back (
00154         shared_ptr<XmlAttribute> (new XmlAttribute (attr)));
00155     }
00156     attr = attr->next;
00157   }
00158 }
00159 
00160 
00161 
00162 XmlElement::~XmlElement()
00163 {
00164   cleanUp();
00165 }
00166 
00167 
00168 
00169 XmlElement * XmlElement::clone()
00170 {
00171   return new XmlElement (*this);
00172 }
00173 
00174 
00175 
00176 XmlElement& XmlElement::operator= (const XmlElement & e)
00177 {
00178   // make sure not same object
00179   if (this != &e) {
00180     cleanUp();
00181     copyFrom (e);
00182   }
00183   return *this;
00184 }
00185 
00186 
00187 
00188 const string XmlElement::getName() const
00189 {
00190   return name_;
00191 }
00192 
00193 
00194 
00195 XmlCharDataVector XmlElement::getCharData()
00196 {
00197   return charData_;
00198 }
00199 
00200 
00201 
00202 shared_ptr<XmlCharData> XmlElement::getFirstNonBlankCharData()
00203 {
00204   XmlCharDataVector vector = this->getCharData();
00205   
00206   for (XmlCharDataVector::iterator it = vector.begin();
00207        it != vector.end();
00208        it++) {
00209     shared_ptr<XmlCharData> xc = *it;
00210     
00211     if (!xc->isBlank()) {
00212       return xc;
00213     }
00214   }
00215   
00216   return shared_ptr<XmlCharData>();
00217 }
00218 
00219 
00220 
00221 XmlElementVector XmlElement::getChildrenElements()
00222 {
00223   return childrenElements_;
00224 }
00225 
00226 
00227 
00228 const XmlAttributeVector XmlElement::getAttributes() const
00229 {
00230   return attributes_;
00231 }
00232 
00233 
00234 
00235 XmlElement::operator string() const
00236 {
00237   stringstream ss;
00238   ss << "<";
00239   ss << this->getName();
00240   
00241   XmlAttributeVector attributes = this->getAttributes();
00242   
00243   if (attributes.size() > 0) {
00244     ss << " ";
00245     XmlAttributeVector::iterator it;
00246     
00247     for (it = attributes.begin(); it != attributes.end(); it++) {
00248       shared_ptr<XmlAttribute> a = *it;
00249       ss << a->getName();
00250       ss << "=\"";
00251       ss << a->getValue();
00252       ss << "\" ";
00253     }
00254   }
00255   
00256   ss << ">";
00257   
00258   XmlItemVector::const_iterator it;
00259   
00260   for (it = items_.begin(); it != items_.end(); it++) {
00261     XmlItem * i = *it;
00262     ss << ( (string) *i);
00263   }
00264   
00265   ss << "</";
00266   ss << this->getName();
00267   ss << ">";
00268   
00269   return ss.str();
00270 }
00271 
00272 
00273 
00274 const bool XmlElement::isXmlElement() const
00275 {
00276   return true;
00277 }
00278 
00279 
00280 
00281 void XmlElement::copyFrom (const XmlElement& e)
00282 {
00283   name_ = e.name_;
00284   
00285   // copy XmlItems
00286   for (XmlItemVector::const_iterator iit = e.items_.begin();
00287        iit != e.items_.end();
00288        iit++) {
00289     XmlItem * i = *iit;
00290     if (i->isXmlElement()) {
00291       XmlElement * xe = (XmlElement*) i;
00292       XmlElement * ne = new XmlElement (*xe);
00293       this->childrenElements_.push_back (shared_ptr<XmlElement> (ne));
00294       this->items_.push_back ( (XmlItem*) ne);
00295     }
00296     else if (i->isXmlCharData()) {
00297       XmlCharData * xc = (XmlCharData*) i;
00298       XmlCharData * nc = new XmlCharData (*xc);
00299       this->charData_.push_back (shared_ptr<XmlCharData> (nc));
00300       this->items_.push_back ( (XmlItem*) nc);
00301     }
00302     else {
00303       throw Exception ("XmlElement::copyFrom : got unidentifiable item");
00304     }
00305   }
00306   
00307   // copy attributes
00308   XmlAttributeVector::const_iterator ait;
00309   for (ait = e.attributes_.begin(); ait != e.attributes_.end(); ait++) {
00310     shared_ptr<XmlAttribute> a = *ait;
00311     XmlAttribute * na = new XmlAttribute (*a);
00312     attributes_.push_back (shared_ptr<XmlAttribute> (na));
00313   }
00314 }
00315 
00316 
00317 
00318 void XmlElement::cleanUp()
00319 {
00320   name_ = string ("UNNAMED");
00321   charData_ = XmlCharDataVector();
00322   childrenElements_ = XmlElementVector();
00323   attributes_ = XmlAttributeVector();
00324   items_ = XmlItemVector();
00325 }
Generated on Fri Mar 4 22:14:58 2011 for MeRMaID::support by  doxygen 1.6.3