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 )
00022 {
00023 }
00024
00025 Tag::Tag( const std::string& name, const std::string& cdata )
00026 : m_name( name ), m_cdata( escape( cdata ) ), m_parent( 0 ), m_type( StanzaUndefined )
00027 {
00028 }
00029
00030 Tag::Tag( Tag *parent, const std::string& name, const std::string& cdata )
00031 : m_name( name ), m_cdata( escape( cdata ) ), m_parent( parent ), m_type( StanzaUndefined )
00032 {
00033 m_parent->addChild( this );
00034 }
00035
00036 Tag::~Tag()
00037 {
00038 TagList::iterator it = m_children.begin();
00039 for( ; it != m_children.end(); ++it )
00040 {
00041 delete (*it);
00042 (*it) = 0;
00043 }
00044 m_children.clear();
00045 }
00046
00047 void Tag::setCData( const std::string& cdata )
00048 {
00049 m_cdata = escape( cdata );
00050 }
00051
00052 void Tag::addCData( const std::string& cdata )
00053 {
00054 m_cdata += escape( cdata );
00055 }
00056
00057 const std::string Tag::xml() const
00058 {
00059 std::string xml;
00060 xml = "<" + m_name;
00061 if( m_attribs.size() )
00062 {
00063 StringMap::const_iterator it_a = m_attribs.begin();
00064 for( ; it_a != m_attribs.end(); ++it_a )
00065 {
00066 xml += " " + (*it_a).first + "='" + (*it_a).second + "'";
00067 }
00068 }
00069
00070 if( m_cdata.empty() && !m_children.size() )
00071 xml += "/>";
00072 else if( m_children.size() )
00073 {
00074 xml += ">";
00075 TagList::const_iterator it_c = m_children.begin();
00076 for( ; it_c != m_children.end(); ++it_c )
00077 {
00078 xml += (*it_c)->xml();
00079 }
00080 xml += "</" + m_name + ">";
00081 }
00082 else if( !m_cdata.empty() )
00083 xml += ">" + m_cdata + "</" + m_name + ">";
00084
00085 return xml;
00086 }
00087
00088 void Tag::addAttribute( const std::string& name, const std::string& value )
00089 {
00090 if( !name.empty() && !value.empty() )
00091 m_attribs[name] = value;
00092 }
00093
00094 void Tag::addAttribute( const std::string& name, int value )
00095 {
00096 if( !name.empty() )
00097 {
00098 std::ostringstream oss;
00099 oss << value;
00100 m_attribs[name] = oss.str();
00101 }
00102 }
00103
00104 void Tag::addChild( Tag *child )
00105 {
00106 if( child )
00107 {
00108 m_children.push_back( child );
00109 child->m_parent = this;
00110 }
00111 }
00112
00113 const std::string Tag::cdata() const
00114 {
00115 return relax( m_cdata );
00116 }
00117
00118 StringMap& Tag::attributes()
00119 {
00120 return m_attribs;
00121 }
00122
00123 Tag::TagList& Tag::children()
00124 {
00125 return m_children;
00126 }
00127
00128 const std::string Tag::findAttribute( const std::string& name ) const
00129 {
00130 StringMap::const_iterator it = m_attribs.find( name );
00131 if( it != m_attribs.end() )
00132 return (*it).second;
00133 else
00134 return "";
00135 }
00136
00137 bool Tag::hasAttribute( const std::string& name, const std::string& value ) const
00138 {
00139 if( name.empty() )
00140 return true;
00141
00142 StringMap::const_iterator it = m_attribs.find( name );
00143 if( it != m_attribs.end() )
00144 return ( ( value.empty() )?( true ):( (*it).second == value ) );
00145 else
00146 return false;
00147 }
00148
00149 Tag* Tag::findChild( const std::string& name )
00150 {
00151 TagList::const_iterator it = m_children.begin();
00152 for( ; it != m_children.end(); ++it )
00153 {
00154 if( (*it)->name() == name )
00155 return (*it);
00156 }
00157
00158 return 0;
00159 }
00160
00161 Tag* Tag::findChild( const std::string& name, const std::string& attr,
00162 const std::string& value )
00163 {
00164 TagList::const_iterator it = m_children.begin();
00165 for( ; it != m_children.end(); ++it )
00166 {
00167 if( ( (*it)->name() == name ) && (*it)->hasAttribute( attr, value ) )
00168 return (*it);
00169 }
00170
00171 return 0;
00172 }
00173
00174 bool Tag::hasChild( const std::string& name,
00175 const std::string& attr, const std::string& value ) const
00176 {
00177 if( name.empty() )
00178 return false;
00179
00180 TagList::const_iterator it = m_children.begin();
00181 for( ; it != m_children.end(); ++it )
00182 {
00183 if( ( (*it)->name() == name )
00184 && (*it)->hasAttribute( attr, value ) )
00185 return true;
00186 }
00187
00188 return false;
00189 }
00190
00191 bool Tag::hasChildWithCData( const std::string& name, const std::string& cdata ) const
00192 {
00193 TagList::const_iterator it = m_children.begin();
00194 for( ; it != m_children.end(); ++it )
00195 {
00196 if( ( (*it)->name() == name ) && !cdata.empty() && ( (*it)->cdata() == cdata ) )
00197 return true;
00198 else if( ( (*it)->name() == name ) && cdata.empty() )
00199 return true;
00200 }
00201
00202 return false;
00203 }
00204
00205 bool Tag::hasChildWithAttrib( const std::string& attr, const std::string& value ) const
00206 {
00207 TagList::const_iterator it = m_children.begin();
00208 for( ; it != m_children.end(); ++it )
00209 {
00210 if( (*it)->hasAttribute( attr, value ) )
00211 return true;
00212 }
00213
00214 return false;
00215 }
00216
00217 Tag* Tag::findChildWithAttrib( const std::string& attr, const std::string& value )
00218 {
00219 TagList::const_iterator it = m_children.begin();
00220 for( ; it != m_children.end(); ++it )
00221 {
00222 if( (*it)->hasAttribute( attr, value ) )
00223 return (*it);
00224 }
00225
00226 return 0;
00227 }
00228
00229 const std::string Tag::replace( const std::string& what, const Duo& duo ) const
00230 {
00231 std::string esc = what;
00232 Duo::const_iterator it = duo.begin();
00233 for( ; it != duo.end(); ++it )
00234 {
00235 size_t lookHere = 0;
00236 size_t foundHere = 0;
00237 while( ( foundHere = esc.find( (*it).first, lookHere ) ) != std::string::npos )
00238 {
00239 esc.replace( foundHere, (*it).first.size(), (*it).second );
00240 lookHere = foundHere + (*it).second.size();
00241 }
00242 }
00243 return esc;
00244 }
00245
00246 const std::string Tag::escape( const std::string& what ) const
00247 {
00248 Duo d;
00249 d.push_back( duo( "&", "&" ) );
00250 d.push_back( duo( "<", "<" ) );
00251 d.push_back( duo( ">", ">" ) );
00252 d.push_back( duo( "'", "'" ) );
00253 d.push_back( duo( "\"", """ ) );
00254
00255 return replace( what, d );
00256 }
00257
00258 const std::string Tag::relax( const std::string& what ) const
00259 {
00260 Duo d;
00261 d.push_back( duo( "<", "<" ) );
00262 d.push_back( duo( ">", ">" ) );
00263 d.push_back( duo( "'", "'" ) );
00264 d.push_back( duo( """, "\"" ) );
00265 d.push_back( duo( "&", "&" ) );
00266
00267 return replace( what, d );
00268 }
00269
00270 Tag* Tag::clone() const
00271 {
00272 Tag *t = new Tag( name(), cdata() );
00273 t->m_attribs = m_attribs;
00274
00275 Tag::TagList::const_iterator it = m_children.begin();
00276 for( ; it != m_children.end(); ++it )
00277 {
00278 t->addChild( (*it)->clone() );
00279 }
00280
00281 return t;
00282 }
00283
00284 }