00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "judo.hpp"
00030 using namespace judo;
00031 using namespace std;
00032
00033
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
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
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
00093 if (this == &e)
00094 return *this;
00095
00096 Node::operator=(e);
00097
00098
00099 if (!_children.empty()) {
00100
00101 for_each(_children.begin(), _children.end(), _releaseChild);
00102 _children.clear();
00103 }
00104 if (!_attribs.empty())
00105 _attribs.clear();
00106
00107 if (!e._children.empty())
00108
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
00442 if (endptr == svalue.c_str())
00443 return defaultvalue;
00444
00445 return result;
00446 }