00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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( "&", "&" ) );
00255 d.push_back( duo( "<", "<" ) );
00256 d.push_back( duo( ">", ">" ) );
00257 d.push_back( duo( "'", "'" ) );
00258 d.push_back( duo( "\"", """ ) );
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( "<", "<" ) );
00267 d.push_back( duo( ">", ">" ) );
00268 d.push_back( duo( "'", "'" ) );
00269 d.push_back( duo( """, "\"" ) );
00270 d.push_back( duo( "<", "<" ) );
00271 d.push_back( duo( ">", ">" ) );
00272 d.push_back( duo( "<", "<" ) );
00273 d.push_back( duo( ">", ">" ) );
00274 d.push_back( duo( "'", "'" ) );
00275 d.push_back( duo( """, "\"" ) );
00276 d.push_back( duo( "<", "<" ) );
00277 d.push_back( duo( ">", ">" ) );
00278 d.push_back( duo( "<", "<" ) );
00279 d.push_back( duo( ">", ">" ) );
00280 d.push_back( duo( "'", "'" ) );
00281 d.push_back( duo( """, "\"" ) );
00282 d.push_back( duo( "<", "<" ) );
00283 d.push_back( duo( ">", ">" ) );
00284 d.push_back( duo( "'", "'" ) );
00285 d.push_back( duo( """, "\"" ) );
00286 d.push_back( duo( "&", "&" ) );
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 }