XmlDocument.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 $Id$
00004 
00005 */
00006 
00007 #include "Error.h"
00008 #include "XmlDataElement.h"
00009 #include "XmlAttributeElement.h"
00010 #include "XmlRegistryElement.h"
00011 
00012 #include "XmlDocument.h"
00013 
00014 // Public methods.
00015 
00016 XmlDocument::XmlDocument() : Support(),
00017   _parser(NULL),
00018   _root(NULL),
00019   _current(NULL)
00020 {
00021   if (!(_parser = XML_ParserCreate(NULL))) {
00022     failure(ERROR(MSG_XML_DOCUMENT_PARSER_CANNOT_CREATE));
00023     return;
00024   }
00025 
00026   XML_SetUserData(_parser, this);
00027   XML_SetElementHandler(_parser, XmlDocument::start, XmlDocument::end);
00028   XML_SetCharacterDataHandler(_parser, XmlDocument::data);
00029 }
00030 
00031 XmlDocument::~XmlDocument()
00032 {
00033   XML_ParserFree(_parser);
00034 }
00035 
00036 int XmlDocument::reset()
00037 {
00038   if (XML_ParserReset(_parser, NULL) == XML_FALSE)
00039     return ERROR(MSG_XML_DOCUMENT_PARSER_CANNOT_RESET);
00040 
00041   return OK;
00042 }
00043 
00044 int XmlDocument::parse(const char *data, const unsigned int size, const bool isFinal)
00045 {
00046   if (XML_Parse(_parser, data, size, isFinal) == XML_STATUS_ERROR)
00047     return ERROR(MSG_XML_DOCUMENT_PARSER, XML_ErrorString(XML_GetErrorCode(_parser)),
00048                  (unsigned long long)XML_GetCurrentLineNumber(_parser), (unsigned long long)XML_GetCurrentColumnNumber(_parser));
00049 
00050   return OK;
00051 }
00052 
00053 int XmlDocument::createElement(const String &tag, XmlElement **element, XmlAttribute *attr)
00054 {
00055   CHECK_POINTER(element);
00056 
00057   int res;
00058 
00059   if (tag.equals(XML_TAG_DATA, true)) {
00060     if (!(*element = new XmlDataElement(attr)))
00061       return ERROR(MSG_OBJECT_CANNOT_CREATE, "XmlDataElement");
00062   } else
00063       if (tag.equals(XML_TAG_REGISTRY, true)) {
00064         if (!(*element = new XmlRegistryElement(attr)))
00065           return ERROR(MSG_OBJECT_CANNOT_CREATE, "XmlRegistryElement");
00066       } else {
00067           unsigned int i;
00068 
00069           *element = NULL;
00070           for (i = 0; XML_ATTR_TAGS[i]; ++i)
00071             if (tag.equals(XML_ATTR_TAGS[i], true)) {
00072               if (!(*element = new XmlAttributeElement(XML_ATTR_TAGS[i], attr)))
00073                 return ERROR(MSG_OBJECT_CANNOT_CREATE, "XmlAttributeElement");
00074               break;
00075             }
00076           if (!*element)
00077             if (!(*element = new XmlElement(tag, attr)))
00078               return ERROR(MSG_OBJECT_CANNOT_CREATE, "XmlElement");
00079         }
00080 
00081   if (FAILED(res = (*element)->failureCode())) {
00082     delete *element;
00083     *element = NULL;
00084     return ERROR_BACKTRACE(res);
00085   }
00086 
00087   if (FAILED(res = (*element)->setDocument(this)))
00088     return ERROR_BACKTRACE(res);
00089 
00090   return OK;
00091 }
00092 
00093 int XmlDocument::removeElement(XmlElement *element)
00094 {
00095   CHECK_POINTER(element);
00096 
00097   XmlElement *p = element->parent();
00098   int res;
00099 
00100   if (p) {
00101     if (FAILED(res = p->removeChild(element)))
00102       return ERROR_BACKTRACE(res);
00103   } else
00104       delete element;
00105   return OK;
00106 }
00107 
00108 XmlElement *XmlDocument::root() const
00109 {
00110   return (XmlElement *)_root;
00111 }
00112 
00113 int XmlDocument::getElementById(const String &id, XmlElement **element) const
00114 {
00115   if (!element)
00116     return ERROR(MSG_NULL_POINTER);
00117 
00118   if (!(*element = _root)) {
00119     WARNING(MSG_XML_DOCUMENT_EMPTY);
00120     return OK;
00121   }
00122 
00123   bool found = false;
00124   int res;
00125 
00126   if (FAILED(res = _getElementById(id, element, found)))
00127     return ERROR_BACKTRACE(res);
00128 
00129   if (!found) {
00130     *element = NULL;
00131     WARNING(MSG_XML_DOCUMENT_ELEMENT_NOT_FOUND, "id", CSTRING(id));
00132   }
00133   return OK;
00134 }
00135 
00136 int XmlDocument::getElementsByName(const String &name, XmlElementCollection &elements) const
00137 {
00138   elements.clear();
00139 
00140   if (!_root) {
00141     WARNING(MSG_XML_DOCUMENT_EMPTY);
00142     return OK;
00143   }
00144 
00145   XmlElement *element = _root;
00146   int res;
00147 
00148   if (FAILED(res = _getElementsByName(name, element, elements)))
00149     return ERROR_BACKTRACE(res);
00150 
00151   return OK;
00152 }
00153 
00154 int XmlDocument::getElementsByTagName(const String &tag, XmlElementCollection &elements) const
00155 {
00156   elements.clear();
00157 
00158   if (!_root) {
00159     WARNING(MSG_XML_DOCUMENT_EMPTY);
00160     return OK;
00161   }
00162 
00163   XmlElement *element = _root;
00164   int res;
00165 
00166   if (FAILED(res = _getElementsByTagName(tag, element, elements)))
00167     return ERROR_BACKTRACE(res);
00168 
00169   return OK;
00170 }
00171 
00172 // Private methods.
00173 
00174 void XMLCALL XmlDocument::start(void *document, const char *tag, const char **attrs)
00175 {
00176   XmlDocument *doc = static_cast<XmlDocument *>(document);
00177   XmlElement *element;
00178   XmlAttribute *rootAttr = NULL;
00179   XmlAttribute *attr = NULL;
00180   int res;
00181 
00182   if (attrs) {
00183     unsigned int i;
00184 
00185     for (i = 0; attrs[i]; i += 2) {
00186       XmlAttribute *a = new XmlAttribute(attrs[i], attrs[i + 1]);
00187       if (!a) {
00188         ERROR(MSG_OBJECT_CANNOT_CREATE, "XmlAttribute");
00189         return;
00190       }
00191       if (FAILED(res = a->failureCode())) {
00192         ERROR_BACKTRACE(res);
00193         delete a;
00194         return;
00195       }
00196       if (attr) {
00197         if (FAILED(res = attr->setNext(a))) {
00198           ERROR_BACKTRACE(res);
00199           return;
00200         }
00201         attr = a;
00202       } else
00203           rootAttr = attr = a;
00204     }
00205   }
00206 
00207   if (FAILED(res = doc->createElement(tag, &element, rootAttr))) {
00208     ERROR_BACKTRACE(res);
00209     return;
00210   }
00211 
00212   if (!doc->_root)
00213     doc->_root = element;
00214   if (doc->_current)
00215     if (FAILED(res = doc->_current->appendChild(element))) {
00216       ERROR_BACKTRACE(res);
00217       return;
00218     }
00219   doc->_current = element;
00220 }
00221 
00222 void XMLCALL XmlDocument::end(void *document, const char *tag)
00223 {
00224   XmlDocument *doc = static_cast<XmlDocument *>(document);
00225 
00226   if (!doc->_current) {
00227     DEBUG("Ignoring closing tag '%s'.", tag);
00228     return;
00229   }
00230 
00231   if (doc->_current && doc->_current->parent())
00232     doc->_current = doc->_current->parent();
00233 
00234   int res;
00235   if (FAILED(res = doc->_current->close()))
00236     ERROR_BACKTRACE(res);
00237 }
00238 
00239 void XMLCALL XmlDocument::data(void *document, const XML_Char *str, int len)
00240 {
00241   XmlDocument *doc = static_cast<XmlDocument *>(document);
00242 
00243   if (!doc->_current)
00244     return;
00245 
00246   int res;
00247 
00248   if (FAILED(res = doc->_current->appendInnerData(String(str, len)))) {
00249     ERROR_BACKTRACE(res);
00250     return;
00251   }
00252 }
00253 
00254 int XmlDocument::_getElementById(const String &id, XmlElement **element, bool &found)
00255 {
00256   if (!element || !*element)
00257     return ERROR(MSG_NULL_POINTER);
00258 
00259   if (id.equals((*element)->id(), true)) {
00260     found = true;
00261     return OK;
00262   }
00263 
00264   XmlElementCollection::const_iterator i = (*element)->_children.begin();
00265   XmlElementCollection::const_iterator e = (*element)->_children.end();
00266   int res;
00267 
00268   while (i != e) {
00269     *element = *i;
00270     if (id.equals((*element)->id(), true)) {
00271       found = true;
00272       break;
00273     } else
00274         if ((*element)->hasChildren())
00275           if (FAILED(res = _getElementById(id, element, found)))
00276             return ERROR_BACKTRACE(res);
00277           else
00278             if (found)
00279               break;
00280     ++i;
00281   }
00282 
00283   return OK;
00284 }
00285 
00286 int XmlDocument::_getElementsByName(const String &name, XmlElement *element, XmlElementCollection &elements)
00287 {
00288   if (!element)
00289     return ERROR(MSG_NULL_POINTER);
00290 
00291   if (name.equals(element->name(), true))
00292     elements.push_back(element);
00293 
00294   XmlElementCollection::const_iterator i = element->_children.begin();
00295   XmlElementCollection::const_iterator e = element->_children.end();
00296   int res;
00297 
00298   while (i != e) {
00299     element = *i;
00300     if (name.equals(element->name(), true))
00301       elements.push_back(element);
00302     if (element->hasChildren())
00303       if (FAILED(res = _getElementsByName(name, element, elements)))
00304         return ERROR_BACKTRACE(res);
00305     ++i;
00306   }
00307 
00308   return OK;
00309 }
00310 
00311 int XmlDocument::_getElementsByTagName(const String &tag, XmlElement *element, XmlElementCollection &elements)
00312 {
00313   if (!element)
00314     return ERROR(MSG_NULL_POINTER);
00315 
00316   if (tag.equals(element->tag(), true))
00317     elements.push_back(element);
00318 
00319   XmlElementCollection::const_iterator i = element->_children.begin();
00320   XmlElementCollection::const_iterator e = element->_children.end();
00321   int res;
00322 
00323   while (i != e) {
00324     element = *i;
00325     if (tag.equals(element->tag(), true))
00326       elements.push_back(element);
00327     if (element->hasChildren())
00328       if (FAILED(res = _getElementsByName(tag, element, elements)))
00329         return ERROR_BACKTRACE(res);
00330     ++i;
00331   }
00332 
00333   return OK;
00334 }

Generated on Thu Sep 6 20:11:25 2007 for Pylon Application Platform by  doxygen 1.5.1