Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

cppdom.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil c-basic-offset: 3 -*- */
00002 // vim:cindent:ts=3:sw=3:et:tw=80:sta:
00003 /*************************************************************** cppdom-cpr beg
00004  * 
00005  * cppdom was forked from the original xmlpp version 0.6 under the LGPL. This
00006  * new, branched xmlpp is under the same LGPL (of course) and is being
00007  * maintained by:
00008  *      Kevin Meinert   <subatomic@users.sourceforge.net>
00009  *      Allen Bierbaum  <allenb@users.sourceforge.net>
00010  *      Ben Scott       <nonchocoboy@users.sourceforge.net>
00011  *
00012  * -----------------------------------------------------------------
00013  *
00014  * xmlpp - an xml parser and validator written in C++
00015  * copyright (c) 2000-2001 Michael Fink
00016  *
00017  * This library is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU Library General Public
00019  * License as published by the Free Software Foundation; either
00020  * version 2 of the License, or (at your option) any later version.
00021  *
00022  * This library is distributed in the hope that it will be useful,
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * Library General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU Library General Public
00028  * License along with this library; if not, write to the
00029  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00030  * Boston, MA 02111-1307, USA.
00031  *
00032  * -----------------------------------------------------------------
00033  * File:          $RCSfile: cppdom.cpp,v $
00034  * Date modified: $Date: 2003/01/03 03:06:46 $
00035  * Version:       $Revision: 1.26 $
00036  * -----------------------------------------------------------------
00037  *
00038  ************************************************************ cppdom-cpr-end */
00045 // needed includes
00046 #include "cppdom.h"
00047 #include "xmlparser.h"
00048 
00049 // namespace declaration
00050 namespace cppdom
00051 {
00052    // XMLError methods
00053 
00054    XMLError::XMLError(XMLErrorCode code)
00055       : mErrorCode(code)
00056    {}
00057 
00058    XMLErrorCode XMLError::getError() const
00059    {
00060       return mErrorCode;
00061    }
00062 
00063    void XMLError::getStrError(std::string& error) const
00064    {
00065    // macro for keeping the errorcode switch short and easy
00066 #define XMLERRORCODE(x,y)  case x: err = y; break;
00067 
00068       const char *err;
00069       switch(mErrorCode)
00070       {
00071          XMLERRORCODE(xml_unknown,"unspecified or unknown error");
00072          XMLERRORCODE(xml_instream_error,"error in the infile stream");
00073          XMLERRORCODE(xml_opentag_expected,"expected an open tag literal '<'");
00074          XMLERRORCODE(xml_opentag_cdata_expected,"expected a '<' or cdata");
00075          XMLERRORCODE(xml_closetag_expected,"expected an '>' closing tag literal");
00076          XMLERRORCODE(xml_pi_doctype_expected,"expected a processing instruction or doctype tag");
00077          XMLERRORCODE(xml_tagname_expected,"expected a tag name after '<' or '</'");
00078          XMLERRORCODE(xml_closetag_slash_expected,"expected a '/' after closing tag literal '<'");
00079          XMLERRORCODE(xml_tagname_close_mismatch,"tag name from start and end tag mismatch");
00080          XMLERRORCODE(xml_attr_equal_expected,"expected '=' after attribute name");
00081          XMLERRORCODE(xml_attr_value_expected,"expected value after 'a' in attribute");
00082          XMLERRORCODE(xml_save_invalid_nodetype,"invalid nodetype encountered while saving");
00083          XMLERRORCODE(xml_filename_invalid,"invalid file name");
00084          XMLERRORCODE(xml_file_access,"could not access file");
00085          XMLERRORCODE(xml_dummy,"dummy error code (this error should never been seen)");
00086       }
00087       error.assign(err);
00088 #undef XMLERRORCODE
00089    }
00090 
00091    std::string XMLError::getString() const
00092    {
00093       std::string err;
00094       getStrError(err);
00095       return err;
00096    }
00097 
00098    std::string XMLError::getInfo() const
00099    {
00100       return "unknown error";
00101    }
00102 
00103    // XMLLocation methods
00104 
00105    XMLLocation::XMLLocation()
00106    {
00107       reset();
00108    }
00109 
00110    int XMLLocation::getLine() const
00111    {
00112       return mLine;
00113    }
00114 
00115    int XMLLocation::getPos() const
00116    {
00117       return mPos;
00118    }
00119 
00120    void XMLLocation::step(int chars)
00121    {
00122       mPos += chars;
00123    }
00124 
00125    void XMLLocation::newline()
00126    {
00127       ++mLine;
00128       mPos = 1;
00129    }
00130 
00131    void XMLLocation::reset()
00132    {
00133       mLine = mPos = 0;
00134    }
00135 
00136    // XMLContext methods
00137 
00138    XMLContext::XMLContext()
00139       : mEventHandler(new XMLEventHandler)
00140    {
00141       mInit = false;
00142       mNextHandle = 0;
00143       mHandleEvents = false;
00144    }
00145 
00146    XMLContext::~XMLContext()
00147    {
00148    }
00149 
00150    std::string XMLContext::getEntity(const std::string& entName)
00151    {
00152       if (!mInit)
00153       {
00154          initContext();
00155       }
00156 
00157       XMLEntityMap::const_iterator iter = mEntities.find(entName);
00158       return (iter == mEntities.end() ? entName : iter->second);
00159    }
00160 
00161    std::string XMLContext::getTagname(XMLTagNameHandle handle)
00162    {
00163       if (!mInit)
00164       {
00165          initContext();
00166       }
00167       XMLTagNameMap::const_iterator iter = mTagNames.find(handle);
00168 
00169       std::string empty("");
00170       return (iter == mTagNames.end() ? empty : iter->second);
00171    }
00172 
00173    XMLTagNameHandle XMLContext::insertTagname(const std::string& tagName)
00174    {
00175       if (!mInit)
00176       {
00177          initContext();
00178       }
00179 
00180       // bugfix: first search, if the tagname is already in the list
00181       // since usually there are not much different tagnames, the search
00182       // shouldn't slow down parsing too much
00183       XMLTagNameMap::const_iterator iter,stop;
00184       iter = mTagNames.begin();
00185       stop = mTagNames.end();
00186 
00187       for(; iter!=stop; ++iter)
00188       {
00189          if (iter->second == tagName)
00190          {
00191             return iter->first;
00192          }
00193       }
00194 
00195       // insert new tagname
00196       XMLTagNameMap::value_type keyvaluepair(mNextHandle, tagName);
00197       mTagNames.insert(keyvaluepair);
00198 
00199       return mNextHandle++;
00200    }
00201 
00202    XMLLocation& XMLContext::getLocation()
00203    {
00204       return mLocation;
00205    }
00206 
00207    void XMLContext::initContext()
00208    {
00209       mInit = true;
00210    }
00211 
00212    void XMLContext::setEventHandler(XMLEventHandlerPtr ehptr)
00213    {
00214       mEventHandler = ehptr;
00215       mHandleEvents = true;
00216    }
00217 
00218    XMLEventHandler& XMLContext::getEventHandler()
00219    {
00220       return *mEventHandler.get();
00221    }
00222 
00223    bool XMLContext::handleEvents() const
00224    {
00225       return mHandleEvents;
00226    }
00227    
00228 
00229    // XMLAttributes methods
00230 
00231    XMLAttribute::XMLAttribute()
00232       : mData("")
00233    {}
00234 
00235    XMLAttribute::XMLAttribute(const XMLAttribute& attr)
00236       : mData(attr.mData)
00237    {}
00238 
00239    XMLAttribute::XMLAttribute(const std::string& val)
00240       : mData(val)
00241    {}
00242 
00243    const std::string& XMLAttribute::getString() const
00244    {
00245       return mData;
00246    }
00247 
00248    XMLAttribute::operator std::string() const
00249    {
00250       return getString();
00251    }
00252 
00253    // XMLAttributes methods
00254 
00255    XMLAttributes::XMLAttributes()
00256    {}
00257 
00258    std::string XMLAttributes::get(const std::string& key) const
00259    {
00260       XMLAttributes::const_iterator iter;
00261 
00262       // try to find the key in the map
00263       iter = find(key);
00264       std::string empty("");
00265       return ((iter == end()) ? empty : iter->second);
00266    }
00267 
00268    void XMLAttributes::set(const std::string& key, const std::string& value)
00269    {
00270       XMLAttributes::iterator iter;
00271 
00272       // try to find the key in the map
00273       iter = find(key);
00274       if (iter != end())
00275       {
00276          (*iter).second = value;
00277       }
00278       else
00279       {
00280          // insert, because the key-value pair was not found
00281          XMLAttributes::value_type pa(key,value);
00282          insert(pa);
00283       }
00284    }
00285 
00286    bool XMLAttributes::has(const std::string& key) const
00287    {
00288       XMLAttributes::const_iterator iter;
00289 
00290       // try to find the key in the map
00291       iter = find(key);
00292       return (iter != end());
00293    }
00294 
00295 
00296    // XMLNode methods
00297 
00298    XMLNode::XMLNode()
00299       : mNodeType(xml_nt_node), mParent(0)
00300    {}
00301 
00302    XMLNode::XMLNode(XMLContextPtr ctx)
00303       : mContext(ctx), mNodeType(xml_nt_node), mParent(0)
00304    {}
00305 
00306    XMLNode::XMLNode(const XMLNode& node)
00307       : mNodeNameHandle(node.mNodeNameHandle)
00308       , mContext(node.mContext)
00309       , mNodeType(node.mNodeType)
00310       , mAttributes(node.mAttributes)
00311       , mCdata(node.mCdata)
00312       , mNodeList(node.mNodeList)
00313       , mParent(node.mParent)
00314    {}
00315 
00316    XMLNode::~XMLNode()
00317    {
00318       for (XMLNodeList::iterator i = mNodeList.begin(); i != mNodeList.end(); ++i)
00319       {
00320          (*i)->mParent = NULL;
00321       }
00322    }
00323 
00324    XMLNode& XMLNode::operator=(const XMLNode& node)
00325    {
00326       mNodeNameHandle = node.mNodeNameHandle;
00327       mContext = node.mContext;
00328       mNodeType = node.mNodeType;
00329       mAttributes = node.mAttributes;
00330       mCdata = node.mCdata;
00331       mNodeList = node.mNodeList;
00332       mParent = node.mParent;
00333       return *this;
00334    }
00335 
00336    XMLNodeType XMLNode::getType() const
00337    {
00338       return mNodeType;
00339    }
00340 
00341    std::string XMLNode::getName()
00342    {
00343       return mContext->getTagname(mNodeNameHandle);
00344    }
00345 
00346    XMLAttributes& XMLNode::getAttrMap()
00347    {
00348       return mAttributes;
00349    }
00350 
00351    XMLAttribute XMLNode::getAttribute(const std::string& name) const
00352    {
00353       return mAttributes.get(name);
00354    }
00355 
00356    bool XMLNode::hasAttribute(const std::string& name) const
00357    {
00358       return mAttributes.has(name);
00359    }
00360 
00361    const std::string& XMLNode::getCdata()
00362    {
00363       return mCdata;
00364    }
00365 
00366    void XMLNode::setType(XMLNodeType type)
00367    {
00368       mNodeType = type;
00369    }
00370 
00371    void XMLNode::setName(const std::string& name)
00372    {
00373       mNodeNameHandle = mContext->insertTagname(name);
00374    }
00375 
00376    void XMLNode::setCdata(const std::string& cdata)
00377    {
00378       mCdata = cdata;
00379    }
00380 
00381    void XMLNode::setAttribute(const std::string& attr, const XMLAttribute& value)
00382    {
00383       mAttributes.set(attr, value.getString());
00384    }
00385 
00386    void XMLNode::addChild(XMLNodePtr& node)
00387    {
00388       node->mParent = this;      // Tell the child who their daddy is
00389       mNodeList.push_back(node);
00390    }
00391 
00392    bool XMLNode::removeChild(XMLNodePtr& node)
00393    {
00394       std::cout << "cppdom::XMLNode::removeChild:  not implemented\n";
00395       return false;
00396    }
00397 
00398    bool XMLNode::removeChild(std::string& childName)
00399    {
00400       std::cout << "cppdom::XMLNode::removeChild:  not implemented\n";
00401       return false;
00402    }
00403 
00404    bool XMLNode::removeChildren(std::string& childName)
00405    {
00406       std::cout << "cppdom::XMLNode::removeChildren:  not implemented\n";
00407       return false;
00408    }
00409 
00410    XMLNodeList& XMLNode::getChildren()
00411    {
00412       return mNodeList;
00413    }
00414 
00416    XMLNodePtr XMLNode::getChild(const std::string& name)
00417    {
00418       // possible speedup: first search if a handle to the childname is existing
00419       XMLNodeList::const_iterator iter;
00420 
00421       // search for first occurance of node
00422       for(iter = mNodeList.begin(); iter != mNodeList.end(); ++iter)
00423       {
00424          XMLNodePtr np = (*iter);
00425          if (np->getName() == name)
00426          {
00427             return np;
00428          }
00429       }
00430 
00431       // no valid child found
00432       return XMLNodePtr();
00433    }
00434 
00435    XMLNodeList XMLNode::getChildren(const std::string& name)
00436    {
00437       XMLNodeList result(0);
00438       XMLNodeList::const_iterator iter;
00439 
00440       // search for all occurances of nodename and insert them into the new list
00441       for(iter = mNodeList.begin(); iter != mNodeList.end(); ++iter)
00442       {
00443          if ((*iter)->getName() == name)
00444          {
00445             result.push_back(*iter);
00446          }
00447       }
00448 
00449       return result;
00450    }
00451 
00452    XMLNodeList XMLNode::getChildren(const char* name)
00453    {
00454       return getChildren(std::string(name));
00455    }
00456 
00457    XMLNode* XMLNode::getParent() const
00458    {
00459       return mParent;
00460    }
00461 
00463    void XMLNode::load(std::istream& in, XMLContextPtr& context)
00464    {
00465       XMLParser parser(in, context->getLocation());
00466       parser.parseNode(*this, context);
00467    }
00468 
00470    void XMLNode::save(std::ostream& out, int indent)
00471    {
00472       // output indendation spaces
00473       for(int i=0; i<indent; ++i)
00474       {
00475          out << ' ';
00476       }
00477 
00478       // output cdata
00479       if (mNodeType == xml_nt_cdata)
00480       {
00481          out << mCdata.c_str() << std::endl;
00482          return;
00483       }
00484 
00485       // output tag name
00486       out << '<' << mContext->getTagname(mNodeNameHandle);
00487 
00488       // output all attributes
00489       XMLAttributes::const_iterator iter, stop;
00490       iter = mAttributes.begin();
00491       stop = mAttributes.end();
00492 
00493       for(; iter!=stop; ++iter)
00494       {
00495          XMLAttributes::value_type attr = *iter;
00496          out << ' ' << attr.first << '=' << '\"' << attr.second << '\"';
00497       }
00498 
00499       // depending on the nodetype, do output
00500       switch(mNodeType)
00501       {
00502       case xml_nt_node:
00503          {
00504             out << '>' << std::endl;
00505 
00506             // output all subnodes
00507             XMLNodeList::const_iterator iter,stop;
00508             iter = mNodeList.begin();
00509             stop = mNodeList.end();
00510 
00511             for(; iter!=stop; ++iter)
00512             {
00513                (*iter)->save(out, indent+1);
00514             }
00515 
00516             // output indendation spaces
00517             for(int i=0;i<indent;i++)
00518             {
00519                out << ' ';
00520             }
00521 
00522             // output closing tag
00523             out << '<' << '/'
00524                << mContext->getTagname(mNodeNameHandle) << '>' << std::endl;
00525          }
00526          break;
00527       case xml_nt_leaf:
00528          // a leaf has no subnodes
00529          out << '/' << '>' << std::endl;
00530          break;
00531       default:
00532          // unknown nodetype
00533          throw XMLError(xml_save_invalid_nodetype);
00534       }
00535    }
00536 
00537    XMLContextPtr XMLNode::getContext()
00538    {
00539       return mContext;
00540    }
00541 
00542 
00543    // XMLDocument methods
00544 
00545    XMLDocument::XMLDocument()
00546    {
00547       mNodeType = xml_nt_document;
00548    }
00549 
00550    XMLDocument::XMLDocument(XMLContextPtr context)
00551       : XMLNode(context)
00552    {
00553       mNodeType = xml_nt_document;
00554    }
00555 
00556    XMLNodeList& XMLDocument::getPiList()
00557    {
00558       return mProcInstructions;
00559    }
00560 
00561    XMLNodeList& XMLDocument::getDtdList()
00562    {
00563       return mDtdRules;
00564    }
00565 
00567    void XMLDocument::load(std::istream& in, XMLContextPtr& context)
00568    {
00569       XMLParser parser(in, context->getLocation());
00570       parser.parseDocument(*this, context);
00571    }
00572 
00576    void XMLDocument::save(std::ostream& out)
00577    {
00578       // output all processing instructions
00579       XMLNodeList::const_iterator iter, stop;
00580       iter = mProcInstructions.begin();
00581       stop = mProcInstructions.end();
00582 
00583       for(; iter!=stop; ++iter)
00584       {
00585          XMLNodePtr np = *iter;
00586 
00587          // output pi tag
00588          out << "<?" << np->getName();
00589 
00590          // output all attributes
00591          XMLAttributes::const_iterator aiter, astop;
00592          aiter = mAttributes.begin();
00593          astop = mAttributes.end();
00594 
00595          for(; aiter!=astop; ++aiter)
00596          {
00597             XMLAttributes::value_type attr = *aiter;
00598             out << ' ' << attr.first << '=' << '\"' << attr.second << '\"';
00599          }
00600          // output closing brace
00601          out << "?>" << std::endl;
00602       }
00603 
00604       // output <!doctype> tag
00605 
00606       // left to do ...
00607 
00608 
00609       // call save() method of the first (and hopefully only) node in XMLDocument
00610       (*mNodeList.begin())->save(out, 0);
00611    }
00612 
00613    void XMLDocument::loadFile(const std::string& filename) throw(XMLError)
00614    {
00615       std::ifstream in;
00616       in.open(filename.c_str(), std::ios::in);
00617 
00618       if (! in.good())
00619       {
00620          throw XMLError(xml_filename_invalid);
00621       }
00622 
00623       load(in, mContext);
00624       in.close();
00625    }
00626 
00627    void XMLDocument::saveFile(const std::string& filename)
00628    {
00629       std::ofstream out;
00630       out.open(filename.c_str(), std::ios::in | std::ios::out);
00631       this->save(out);
00632       out.close();
00633    }
00634 }

Generated on Thu Jan 2 21:29:17 2003 for cppdom by doxygen1.2.15