Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members  

Element.cpp

00001 //============================================================================
00002 // Project:       Jabber Universal Document Objects (Judo)
00003 // Filename:      Element.cpp
00004 // Description:   judo::Element
00005 // Created at:    Mon Jul  2 17:12:54 2001
00006 // Modified at:   Wed Oct 17 11:35:31 2001
00007 // 
00008 //   License:
00009 // 
00010 // The contents of this file are subject to the Jabber Open Source License
00011 // Version 1.0 (the "License").  You may not copy or use this file, in either
00012 // source code or executable form, except in compliance with the License.  You
00013 // may obtain a copy of the License at http://www.jabber.com/license/ or at
00014 // http://www.opensource.org/.  
00015 //
00016 // Software distributed under the License is distributed on an "AS IS" basis,
00017 // WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
00018 // for the specific language governing rights and limitations under the
00019 // License.
00020 //
00021 //   Copyrights
00022 //
00023 // Portions created by or assigned to Jabber.com, Inc. are 
00024 // Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  
00025 // 
00026 // $Id: Element.cpp,v 1.3 2003/02/01 22:49:57 temas Exp $
00027 //============================================================================
00028 
00029 #include "judo.hpp"
00030 using namespace judo;
00031 using namespace std;
00032 
00033 // Internal node copier predicate
00034 class P_NodeCopier : 
00035     public unary_function<Node*, void>
00036 {
00037 public:
00038     explicit P_NodeCopier(Element& parent) 
00039         : _parent(parent) 
00040         {}
00041     void operator()(const Node* n) const 
00042         {
00043             if (n->getType() == Node::ntElement)
00044                 _parent.appendChild(new Element(*static_cast<const Element*>(n)));
00045             else
00046                 _parent.appendChild(new CDATA(*static_cast<const CDATA*>(n)));
00047         }
00048 private:
00049     Element& _parent;
00050 };
00051 
00057 Element::Element(const string& name, const char** attribs)
00058     : Node(name, Node::ntElement)
00059 {
00060     // Process expat attribs
00061     if (attribs != NULL)
00062     {
00063         int i = 0;
00064         while (attribs[i] != '\0')
00065         {
00066             _attribs.insert(make_pair(string(attribs[i]), string(attribs[i+1])));
00067             i += 2;
00068         }
00069     }
00070 }
00071 
00072 // Copy constructor
00073 Element::Element(const Element& e)
00074     : Node(e.getName(), Node::ntElement),
00075       _attribs(e._attribs)
00076 {
00077     for_each(e._children.begin(), e._children.end(), P_NodeCopier(*this));
00078 }
00079 
00080 static void _releaseChild(Node* n)
00081 {
00082     delete n;
00083 }
00084 
00085 Element::~Element()
00086 {
00087     for_each(_children.begin(), _children.end(), _releaseChild);
00088 }
00089 
00090 Element& Element::operator=(const Element& e)
00091 {
00092     // Check for assignment to self
00093     if (this == &e)
00094           return *this;
00095     // Copy underlying members
00096     Node::operator=(e);
00097 
00098     // Release pre-existing children/attribs if necessary
00099     if (!_children.empty()) {
00100          // Release child nodes
00101          for_each(_children.begin(), _children.end(), _releaseChild);
00102          _children.clear();
00103     }
00104     if (!_attribs.empty()) 
00105          _attribs.clear();
00106      // Copy children/attribs from t
00107      if (!e._children.empty())
00108           // Copy each individual element in t._Children
00109           for_each(e._children.begin(), e._children.end(), P_NodeCopier(*this));
00110      if (!e._attribs.empty())
00111           _attribs = e._attribs;
00112 
00113      return *this;
00114 }
00115 
00122 Element* Element::addElement(const string& name, const char** attribs)
00123 {
00124     Element* result = new Element(name, attribs);
00125     _children.push_back(result);
00126     return result;
00127 }
00128 
00137 Element* Element::addElement(const string& name, const string& value, bool escaped)
00138 {
00139     Element* result = addElement(name);
00140     result->addCDATA(value.c_str(), value.size(), escaped);
00141     return result;
00142 }
00143 
00144 
00154 CDATA* Element::addCDATA(const char* data, int datasz, bool escaped)
00155 {
00156     CDATA *result;
00157     if (!_children.empty() && _children.back()->getType() == Node::ntCDATA)
00158     {
00159         result = static_cast<CDATA*>(_children.back());
00160         result->appendText(data, datasz, escaped);
00161     }
00162     else
00163     {
00164         result = new CDATA(data, datasz, escaped);
00165         _children.push_back(result);
00166     }
00167     return result;
00168 }
00169 
00170 
00176 void Element::putAttrib(const string& name, const string& value)
00177 {
00178     _attribs[name] = value;
00179 }
00180 
00186 string Element::getAttrib(const string& name) const
00187 {
00188     map<string,string>::const_iterator it = _attribs.find(name);
00189     if (it != _attribs.end())
00190         return it->second;
00191     else
00192         return "";
00193 }
00194 
00199 void Element::delAttrib(const string& name)
00200 {
00201     _attribs.erase(name);
00202 }
00203 
00211 bool Element::cmpAttrib(const string& name, const string& value) const
00212 {
00213     map<string, string>::const_iterator it = _attribs.find(name);
00214     if (it != _attribs.end())
00215         return it->second == value;
00216     else
00217         return false;
00218 }
00219 
00225 string Element::toString() const
00226 {
00227     string result;
00228     XMLAccumulator acc(result);
00229 
00230     accumulate(acc);
00231 
00232     return result;
00233 }
00234 
00245 string Element::toStringEx(bool recursive, bool closetag) const
00246 {
00247     string result;
00248 
00249     XMLAccumulator acc(result);
00250     
00251     acc << "<" << getName();
00252     for_each(_attribs.begin(), _attribs.end(), acc);
00253 
00254     if (recursive && !_children.empty())
00255     {
00256         acc << ">";
00257         for_each(_children.begin(), _children.end(), acc);
00258         if (closetag)
00259             acc << "</" << getName() << ">";
00260     }
00261     else
00262     {
00263         if (closetag)
00264             acc << "/>";
00265         else
00266             acc << ">";
00267     }
00268     return result;
00269 }
00270 
00276 void Element::accumulate(XMLAccumulator& acc) const
00277 {
00278     acc << "<" << getName();
00279     for_each(_attribs.begin(), _attribs.end(), acc);
00280     if (!_children.empty())
00281     {
00282         acc << ">";
00283         for_each(_children.begin(), _children.end(), acc);
00284         acc << "</" << getName() << ">";
00285     }
00286     else
00287     {
00288         acc << "/>";
00289     }
00290 }
00291 
00296 string Element::getCDATA() const
00297 {
00298     list<Node*>::const_iterator it = _children.begin();
00299     for (; it != _children.end(); ++it)
00300     {
00301         if ((*it)->getType() == ntCDATA)
00302             break;
00303     }
00304     if (it != _children.end())
00305         return static_cast<const CDATA*>(*it)->getText();
00306     else
00307         return string();
00308 }
00309 
00316 Element::iterator Element::find(const string& name, Node::Type type)
00317 {
00318     iterator result = begin();
00319     for (; result != end(); ++result)
00320     {
00321         if (((*result)->getType() == type) && 
00322             ((*result)->getName() == name))
00323             break;
00324     }
00325     return result;
00326 }
00327 
00334 Element::const_iterator Element::find(const string& name, Node::Type type) const
00335 {
00336     const_iterator result = begin();
00337     for (; result != end(); ++result)
00338     {
00339         if (((*result)->getType() == type) &&
00340             ((*result)->getName() == name))
00341             break;
00342     }
00343     return result;
00344 }
00345 
00346 
00354 Element* Element::findElement(const string& name)
00355 {
00356     iterator result = find(name, Node::ntElement);
00357     if (result != end())
00358         return static_cast<Element*>(*result);
00359     else
00360         return NULL;
00361 }
00362 
00370 const Element* Element::findElement(const string& name) const
00371 {
00372     const_iterator result = find(name, Node::ntElement);
00373     if (result != end())
00374         return static_cast<const Element*>(*result);
00375     else
00376         return NULL;
00377 }
00378 
00379 
00385 void Element::eraseElement(const string& name)
00386 {
00387     iterator it = find(name, Node::ntElement);
00388     if (it != end())
00389         erase(it);
00390 }
00391 
00398 Node* Element::detachChild(iterator it)
00399 {
00400     Node* retval = *it;
00401     _children.erase(it);
00402     return retval;
00403 }
00404 
00412 std::string Element::getChildCData(const std::string& name) const
00413 {
00414     const Element* child = findElement(name);
00415     return (child != NULL) ? child->getCDATA() : string();
00416 }
00417 
00429 int Element::getChildCDataAsInt(const std::string& name, int defaultvalue) const
00430 {
00431     const judo::Element* child = findElement(name);
00432     if (child == NULL)
00433         return defaultvalue;
00434 
00435     string svalue = child->getCDATA();
00436     if (svalue.empty())
00437         return defaultvalue;
00438 
00439     char* endptr = NULL;
00440     int result = strtol(svalue.c_str(), &endptr, 10);
00441     // If endptr is the same as the original string, no valid digits were found
00442     if (endptr == svalue.c_str())
00443         return defaultvalue;
00444 
00445     return result;
00446 }

Generated on Thu Jul 24 13:31:50 2003 for jabberoo by doxygen1.3-rc3