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