tag.cpp

00001 /*
00002   Copyright (c) 2005-2006 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 #include "tag.h"
00015 
00016 #include <sstream>
00017 
00018 namespace gloox
00019 {
00020   Tag::Tag()
00021     : m_parent( 0 ), m_type( StanzaUndefined ), m_incoming( false )
00022   {
00023   }
00024 
00025   Tag::Tag( const std::string& name, const std::string& cdata, bool incoming )
00026     : m_name( incoming ? relax( name ) : name ),
00027       m_cdata( incoming ? relax( cdata ) : cdata ),
00028       m_parent( 0 ), m_type( StanzaUndefined ), m_incoming( incoming )
00029   {
00030   }
00031 
00032   Tag::Tag( Tag *parent, const std::string& name, const std::string& cdata, bool incoming )
00033     : m_name( incoming ? relax( name ) : name ),
00034       m_cdata( incoming ? relax( cdata ) : cdata ),
00035       m_parent( parent ), m_type( StanzaUndefined ), m_incoming( incoming )
00036   {
00037     m_parent->addChild( this );
00038   }
00039 
00040   Tag::~Tag()
00041   {
00042     TagList::iterator it = m_children.begin();
00043     for( ; it != m_children.end(); ++it )
00044     {
00045       delete (*it);
00046       (*it) = 0;
00047     }
00048     m_children.clear();
00049     m_parent = 0;
00050   }
00051 
00052   void Tag::setCData( const std::string& cdata )
00053   {
00054     m_cdata = m_incoming ? relax( cdata ) : cdata;
00055   }
00056 
00057   void Tag::addCData( const std::string& cdata )
00058   {
00059     m_cdata += m_incoming ? relax( cdata ) : cdata;
00060   }
00061 
00062   const std::string Tag::xml() const
00063   {
00064     std::string xml;
00065     xml = "<" + escape( m_name );
00066     if( m_attribs.size() )
00067     {
00068       StringMap::const_iterator it_a = m_attribs.begin();
00069       for( ; it_a != m_attribs.end(); ++it_a )
00070       {
00071         xml += " " + escape( (*it_a).first ) + "='" + escape( (*it_a).second ) + "'";
00072       }
00073     }
00074 
00075     if( m_cdata.empty() && !m_children.size() )
00076       xml += "/>";
00077     else if( m_children.size() )
00078     {
00079       xml += ">";
00080       TagList::const_iterator it_c = m_children.begin();
00081       for( ; it_c != m_children.end(); ++it_c )
00082       {
00083         xml += (*it_c)->xml();
00084       }
00085       xml += "</" + escape( m_name ) + ">";
00086     }
00087     else if( !m_cdata.empty() )
00088       xml += ">" + escape( m_cdata ) + "</" + escape( m_name ) + ">";
00089 
00090     return xml;
00091   }
00092 
00093   void Tag::addAttribute( const std::string& name, const std::string& value )
00094   {
00095     if( !name.empty() && !value.empty() )
00096       m_attribs[m_incoming ? relax( name ) : name] = m_incoming ? relax( value ) : value;
00097   }
00098 
00099   void Tag::addAttribute( const std::string& name, int value )
00100   {
00101     if( !name.empty() )
00102     {
00103       std::ostringstream oss;
00104       oss << value;
00105       m_attribs[m_incoming ? relax( name ) : name] = oss.str();
00106     }
00107   }
00108 
00109   void Tag::addChild( Tag *child )
00110   {
00111     if( child )
00112     {
00113       m_children.push_back( child );
00114       child->m_parent = this;
00115     }
00116   }
00117 
00118   const std::string Tag::cdata() const
00119   {
00120     return m_cdata;
00121   }
00122 
00123   StringMap& Tag::attributes()
00124   {
00125     return m_attribs;
00126   }
00127 
00128   Tag::TagList& Tag::children()
00129   {
00130     return m_children;
00131   }
00132 
00133   const std::string Tag::findAttribute( const std::string& name ) const
00134   {
00135     StringMap::const_iterator it = m_attribs.find( name );
00136     if( it != m_attribs.end() )
00137       return (*it).second;
00138     else
00139       return "";
00140   }
00141 
00142   bool Tag::hasAttribute( const std::string& name, const std::string& value ) const
00143   {
00144     if( name.empty() )
00145       return true;
00146 
00147     StringMap::const_iterator it = m_attribs.find( name );
00148     if( it != m_attribs.end() )
00149       return ( ( value.empty() )?( true ):( (*it).second == value ) );
00150     else
00151       return false;
00152   }
00153 
00154   Tag* Tag::findChild( const std::string& name )
00155   {
00156     TagList::const_iterator it = m_children.begin();
00157     for( ; it != m_children.end(); ++it )
00158     {
00159       if( (*it)->name() == name )
00160         return (*it);
00161     }
00162 
00163     return 0;
00164   }
00165 
00166   Tag* Tag::findChild( const std::string& name, const std::string& attr,
00167                        const std::string& value )
00168   {
00169     TagList::const_iterator it = m_children.begin();
00170     for( ; it != m_children.end(); ++it )
00171     {
00172       if( ( (*it)->name() == name ) && (*it)->hasAttribute( attr, value ) )
00173         return (*it);
00174     }
00175 
00176     return 0;
00177   }
00178 
00179   bool Tag::hasChild( const std::string& name,
00180                       const std::string& attr, const std::string& value ) const
00181   {
00182     if( name.empty() )
00183       return false;
00184 
00185     TagList::const_iterator it = m_children.begin();
00186     for( ; it != m_children.end(); ++it )
00187     {
00188       if( ( (*it)->name() == name )
00189               && (*it)->hasAttribute( attr, value ) )
00190         return true;
00191     }
00192 
00193     return false;
00194   }
00195 
00196   bool Tag::hasChildWithCData( const std::string& name, const std::string& cdata ) const
00197   {
00198     TagList::const_iterator it = m_children.begin();
00199     for( ; it != m_children.end(); ++it )
00200     {
00201       if( ( (*it)->name() == name ) && !cdata.empty() && ( (*it)->cdata() == cdata ) )
00202         return true;
00203       else if( ( (*it)->name() == name ) && cdata.empty() )
00204         return true;
00205     }
00206 
00207     return false;
00208   }
00209 
00210   bool Tag::hasChildWithAttrib( const std::string& attr, const std::string& value ) const
00211   {
00212     TagList::const_iterator it = m_children.begin();
00213     for( ; it != m_children.end(); ++it )
00214     {
00215       if( (*it)->hasAttribute( attr, value ) )
00216         return true;
00217     }
00218 
00219     return false;
00220   }
00221 
00222   Tag* Tag::findChildWithAttrib( const std::string& attr, const std::string& value )
00223   {
00224     TagList::const_iterator it = m_children.begin();
00225     for( ; it != m_children.end(); ++it )
00226     {
00227       if( (*it)->hasAttribute( attr, value ) )
00228         return (*it);
00229     }
00230 
00231     return 0;
00232   }
00233 
00234   const std::string Tag::replace( const std::string& what, const Duo& duo ) const
00235   {
00236     std::string esc = what;
00237     Duo::const_iterator it = duo.begin();
00238     for( ; it != duo.end(); ++it )
00239     {
00240       size_t lookHere = 0;
00241       size_t foundHere = 0;
00242       while( ( foundHere = esc.find( (*it).first, lookHere ) ) != std::string::npos )
00243       {
00244         esc.replace( foundHere, (*it).first.size(), (*it).second );
00245         lookHere = foundHere + (*it).second.size();
00246       }
00247     }
00248     return esc;
00249   }
00250 
00251   const std::string Tag::escape( const std::string& what ) const
00252   {
00253     Duo d;
00254     d.push_back( duo( "&", "&amp;" ) );
00255     d.push_back( duo( "<", "&lt;" ) );
00256     d.push_back( duo( ">", "&gt;" ) );
00257     d.push_back( duo( "'", "&apos;" ) );
00258     d.push_back( duo( "\"", "&quot;" ) );
00259 
00260     return replace( what, d );
00261   }
00262 
00263   const std::string Tag::relax( const std::string& what ) const
00264   {
00265     Duo d;
00266     d.push_back( duo( "&#60;", "<" ) );
00267     d.push_back( duo( "&#62;", ">" ) );
00268     d.push_back( duo( "&#39;", "'" ) );
00269     d.push_back( duo( "&#34;", "\"" ) );
00270     d.push_back( duo( "&#x3c;", "<" ) );
00271     d.push_back( duo( "&#x3e;", ">" ) );
00272     d.push_back( duo( "&#x3C;", "<" ) );
00273     d.push_back( duo( "&#x3E;", ">" ) );
00274     d.push_back( duo( "&#x27;", "'" ) );
00275     d.push_back( duo( "&#x22;", "\"" ) );
00276     d.push_back( duo( "&#X3c;", "<" ) );
00277     d.push_back( duo( "&#X3e;", ">" ) );
00278     d.push_back( duo( "&#X3C;", "<" ) );
00279     d.push_back( duo( "&#X3E;", ">" ) );
00280     d.push_back( duo( "&#X27;", "'" ) );
00281     d.push_back( duo( "&#X22;", "\"" ) );
00282     d.push_back( duo( "&lt;", "<" ) );
00283     d.push_back( duo( "&gt;", ">" ) );
00284     d.push_back( duo( "&apos;", "'" ) );
00285     d.push_back( duo( "&quot;", "\"" ) );
00286     d.push_back( duo( "&amp;", "&" ) );
00287 
00288     return replace( what, d );
00289   }
00290 
00291   Tag* Tag::clone() const
00292   {
00293     Tag *t = new Tag( name(), cdata() );
00294     t->m_attribs = m_attribs;
00295 
00296     Tag::TagList::const_iterator it = m_children.begin();
00297     for( ; it != m_children.end(); ++it )
00298     {
00299       t->addChild( (*it)->clone() );
00300     }
00301 
00302     return t;
00303   }
00304 
00305 }

Generated on Tue May 1 14:20:20 2007 for gloox by  doxygen 1.5.1