00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "tag.h"
00015 #include "util.h"
00016
00017 #include <stdlib.h>
00018
00019 #ifdef _WIN32_WCE
00020 # include <cmath>
00021 #else
00022 # include <sstream>
00023 #endif
00024
00025 #include <algorithm>
00026
00027 namespace gloox
00028 {
00029
00030
00031 Tag::Attribute::Attribute( Tag* parent, const std::string& name, const std::string& value,
00032 const std::string& xmlns )
00033 : m_parent( parent )
00034 {
00035 if( m_parent )
00036 m_parent->addAttribute( this );
00037
00038 init( name, value, xmlns );
00039 }
00040
00041 Tag::Attribute::Attribute( const std::string& name, const std::string& value,
00042 const std::string& xmlns )
00043 : m_parent( 0 )
00044 {
00045 init( name, value, xmlns );
00046 }
00047
00048 Tag::Attribute::Attribute( const Attribute& attr )
00049 : m_parent( attr.m_parent ), m_name( attr.m_name ), m_value( attr.m_value ),
00050 m_xmlns( attr.m_xmlns ), m_prefix( attr.m_prefix )
00051 {
00052 }
00053
00054 void Tag::Attribute::init( const std::string& name, const std::string& value,
00055 const std::string& xmlns )
00056 {
00057 if( util::checkValidXMLChars( xmlns ) )
00058 m_xmlns = xmlns;
00059 else
00060 return;
00061
00062 if( util::checkValidXMLChars( value ) )
00063 m_value = value;
00064 else
00065 return;
00066
00067 if( util::checkValidXMLChars( name ) )
00068 m_name = name;
00069 else
00070 return;
00071 }
00072
00073 bool Tag::Attribute::setValue( const std::string& value )
00074 {
00075 if( !util::checkValidXMLChars( value ) )
00076 return false;
00077
00078 m_value = value;
00079 return true;
00080 }
00081
00082 bool Tag::Attribute::setXmlns( const std::string& xmlns )
00083 {
00084 if( !util::checkValidXMLChars( xmlns ) )
00085 return false;
00086
00087 m_xmlns = xmlns;
00088 return true;
00089 }
00090
00091 bool Tag::Attribute::setPrefix( const std::string& prefix )
00092 {
00093 if( !util::checkValidXMLChars( prefix ) )
00094 return false;
00095
00096 m_prefix = prefix;
00097 return true;
00098 }
00099
00100 const std::string& Tag::Attribute::xmlns() const
00101 {
00102 if( !m_xmlns.empty() )
00103 return m_xmlns;
00104
00105 if( m_parent )
00106 return m_parent->xmlns( m_prefix );
00107
00108 return EmptyString;
00109 }
00110
00111 const std::string& Tag::Attribute::prefix() const
00112 {
00113 if( !m_prefix.empty() )
00114 return m_prefix;
00115
00116 if( m_parent )
00117 return m_parent->prefix( m_xmlns );
00118
00119 return EmptyString;
00120 }
00121
00122 const std::string Tag::Attribute::xml() const
00123 {
00124 if( m_name.empty() )
00125 return EmptyString;
00126
00127 std::string xml;
00128 xml += ' ';
00129 if( !m_prefix.empty() )
00130 {
00131 xml += m_prefix;
00132 xml += ':';
00133 }
00134 xml += m_name;
00135 xml += "='";
00136 xml += util::escape( m_value );
00137 xml += '\'';
00138
00139 return xml;
00140 }
00141
00142
00143
00144 Tag::Tag( const std::string& name, const std::string& cdata )
00145 : m_parent( 0 ), m_children( 0 ), m_cdata( 0 ),
00146 m_attribs( 0 ), m_nodes( 0 ),
00147 m_xmlnss( 0 )
00148 {
00149 addCData( cdata );
00150
00151 if( util::checkValidXMLChars( name ) )
00152 m_name = name;
00153 }
00154
00155 Tag::Tag( Tag* parent, const std::string& name, const std::string& cdata )
00156 : m_parent( parent ), m_children( 0 ), m_cdata( 0 ),
00157 m_attribs( 0 ), m_nodes( 0 ),
00158 m_xmlnss( 0 )
00159 {
00160 if( m_parent )
00161 m_parent->addChild( this );
00162
00163 addCData( cdata );
00164
00165 if( util::checkValidXMLChars( name ) )
00166 m_name = name;
00167 }
00168
00169 Tag::Tag( const std::string& name,
00170 const std::string& attrib,
00171 const std::string& value )
00172 : m_parent( 0 ), m_children( 0 ), m_cdata( 0 ),
00173 m_attribs( 0 ), m_nodes( 0 ),
00174 m_name( name ), m_xmlnss( 0 )
00175 {
00176 addAttribute( attrib, value );
00177
00178 if( util::checkValidXMLChars( name ) )
00179 m_name = name;
00180 }
00181
00182 Tag::Tag( Tag* parent, const std::string& name,
00183 const std::string& attrib,
00184 const std::string& value )
00185 : m_parent( parent ), m_children( 0 ), m_cdata( 0 ),
00186 m_attribs( 0 ), m_nodes( 0 ),
00187 m_name( name ), m_xmlnss( 0 )
00188 {
00189 if( m_parent )
00190 m_parent->addChild( this );
00191
00192 addAttribute( attrib, value );
00193
00194 if( util::checkValidXMLChars( name ) )
00195 m_name = name;
00196 }
00197
00198 Tag::Tag( Tag* tag )
00199 : m_parent( 0 ), m_children( 0 ), m_cdata( 0 ), m_attribs( 0 ),
00200 m_nodes( 0 ), m_xmlnss( 0 )
00201 {
00202 if( !tag )
00203 return;
00204
00205 m_children = tag->m_children;
00206 m_cdata = tag->m_cdata;
00207 m_attribs = tag->m_attribs;
00208 m_nodes = tag->m_nodes;
00209 m_name = tag->m_name;
00210 m_xmlns = tag->m_xmlns;
00211 m_xmlnss = tag->m_xmlnss;
00212
00213 tag->m_nodes = 0;
00214 tag->m_cdata = 0;
00215 tag->m_attribs = 0;
00216 tag->m_children = 0;
00217 tag->m_xmlnss = 0;
00218
00219 if( m_attribs )
00220 {
00221 AttributeList::iterator it = m_attribs->begin();
00222 while( it != m_attribs->end() )
00223 (*it++)->m_parent = this;
00224 }
00225
00226 if( m_children )
00227 {
00228 TagList::iterator it = m_children->begin();
00229 while( it != m_children->end() )
00230 (*it++)->m_parent = this;
00231 }
00232 }
00233
00234 Tag::~Tag()
00235 {
00236 if( m_cdata )
00237 {
00238
00239
00240 StringPList::iterator it = m_cdata->begin();
00241 StringPList::iterator it2;
00242 while( it != m_cdata->end() )
00243 {
00244 it2 = it++;
00245 delete (*it2);
00246 m_cdata->erase( it2 );
00247 }
00248
00249 }
00250 if( m_attribs )
00251 {
00252
00253
00254 AttributeList::iterator it = m_attribs->begin();
00255 AttributeList::iterator it2;
00256 while( it != m_attribs->end() )
00257 {
00258 it2 = it++;
00259 delete (*it2);
00260 m_attribs->erase( it2 );
00261 }
00262
00263 }
00264 if( m_children )
00265 {
00266
00267
00268 TagList::iterator it = m_children->begin();
00269 TagList::iterator it2;
00270 while( it != m_children->end() )
00271 {
00272 it2 = it++;
00273 delete (*it2);
00274 m_children->erase( it2 );
00275 }
00276
00277 }
00278 if( m_nodes )
00279 {
00280
00281
00282 NodeList::iterator it = m_nodes->begin();
00283 NodeList::iterator it2;
00284 while( it != m_nodes->end() )
00285 {
00286 it2 = it++;
00287 delete (*it2);
00288 m_nodes->erase( it2 );
00289 }
00290
00291 }
00292
00293 delete m_cdata;
00294 delete m_attribs;
00295 delete m_children;
00296 delete m_nodes;
00297 delete m_xmlnss;
00298
00299 m_parent = 0;
00300 }
00301
00302 bool Tag::operator==( const Tag& right ) const
00303 {
00304 if( m_name != right.m_name || m_xmlns != right.m_xmlns )
00305 return false;
00306
00307 if( m_cdata && right.m_cdata )
00308 {
00309 StringPList::const_iterator ct = m_cdata->begin();
00310 StringPList::const_iterator ct_r = right.m_cdata->begin();
00311 while( ct != m_cdata->end() && ct_r != right.m_cdata->end() && *(*ct) == *(*ct_r) )
00312 {
00313 ++ct;
00314 ++ct_r;
00315 }
00316 if( ct != m_cdata->end() )
00317 return false;
00318 }
00319 else if( m_cdata || right.m_cdata )
00320 return false;
00321
00322 if( m_children && right.m_children )
00323 {
00324 TagList::const_iterator it = m_children->begin();
00325 TagList::const_iterator it_r = right.m_children->begin();
00326 while( it != m_children->end() && it_r != right.m_children->end() && *(*it) == *(*it_r) )
00327 {
00328 ++it;
00329 ++it_r;
00330 }
00331 if( it != m_children->end() )
00332 return false;
00333 }
00334 else if( m_children || right.m_children )
00335 return false;
00336
00337 if( m_attribs && right.m_attribs )
00338 {
00339 AttributeList::const_iterator at = m_attribs->begin();
00340 AttributeList::const_iterator at_r = right.m_attribs->begin();
00341 while( at != m_attribs->end() && at_r != right.m_attribs->end() && *(*at) == *(*at_r) )
00342 {
00343 ++at;
00344 ++at_r;
00345 }
00346 if( at != m_attribs->end() )
00347 return false;
00348 }
00349 else if( m_attribs || right.m_attribs )
00350 return false;
00351
00352 return true;
00353 }
00354
00355 const std::string Tag::xml() const
00356 {
00357 if( m_name.empty() )
00358 return EmptyString;
00359
00360 std::string xml = "<";
00361 if( !m_prefix.empty() )
00362 {
00363 xml += m_prefix;
00364 xml += ':';
00365 }
00366 xml += m_name;
00367 if( m_attribs && !m_attribs->empty() )
00368 {
00369 AttributeList::const_iterator it_a = m_attribs->begin();
00370 for( ; it_a != m_attribs->end(); ++it_a )
00371 {
00372 xml += (*it_a)->xml();
00373 }
00374 }
00375
00376 if( !m_nodes || m_nodes->empty() )
00377 xml += "/>";
00378 else
00379 {
00380 xml += '>';
00381 NodeList::const_iterator it_n = m_nodes->begin();
00382 for( ; it_n != m_nodes->end(); ++it_n )
00383 {
00384 switch( (*it_n)->type )
00385 {
00386 case TypeTag:
00387 xml += (*it_n)->tag->xml();
00388 break;
00389 case TypeString:
00390 xml += util::escape( *((*it_n)->str) );
00391 break;
00392 }
00393 }
00394 xml += "</";
00395 if( !m_prefix.empty() )
00396 {
00397 xml += m_prefix;
00398 xml += ':';
00399 }
00400 xml += m_name;
00401 xml += '>';
00402 }
00403
00404 return xml;
00405 }
00406
00407 bool Tag::addAttribute( Attribute* attr )
00408 {
00409 if( !attr )
00410 return false;
00411
00412 if( !(*attr) )
00413 {
00414 delete attr;
00415 return false;
00416 }
00417
00418 if( !m_attribs )
00419 m_attribs = new AttributeList();
00420
00421 AttributeList::iterator it = m_attribs->begin();
00422 for( ; it != m_attribs->end(); ++it )
00423 {
00424 if( (*it)->name() == attr->name()
00425 && ( (*it)->xmlns() == attr->xmlns() || (*it)->prefix() == attr->prefix() ) )
00426 {
00427 delete (*it);
00428 (*it) = attr;
00429 return true;
00430 }
00431 }
00432
00433 m_attribs->push_back( attr );
00434
00435 return true;
00436 }
00437
00438 bool Tag::addAttribute( const std::string& name, const std::string& value )
00439 {
00440 if( name.empty() || value.empty() )
00441 return false;
00442
00443 return addAttribute( new Attribute( name, value ) );
00444 }
00445
00446 bool Tag::addAttribute( const std::string& name, int value )
00447 {
00448 if( name.empty() )
00449 return false;
00450
00451 return addAttribute( name, util::int2string( value ) );
00452 }
00453
00454 bool Tag::addAttribute( const std::string& name, long value )
00455 {
00456 if( name.empty() )
00457 return false;
00458
00459 #ifdef _WIN32_WCE
00460 const int len = 4 + (int)std::log10( value ? value : 1 ) + 1;
00461 char* tmp = new char[len];
00462 sprintf( tmp, "%ld", value );
00463 std::string ret( tmp, len );
00464 delete[] tmp;
00465 return addAttribute( name, ret );
00466 #else
00467 std::ostringstream oss;
00468 oss << value;
00469 return addAttribute( name, oss.str() );
00470 #endif
00471 }
00472
00473 void Tag::setAttributes( const AttributeList& attributes )
00474 {
00475 if( !m_attribs )
00476 m_attribs = new AttributeList( attributes );
00477 else
00478 {
00479
00480
00481 AttributeList::iterator it = m_attribs->begin();
00482 AttributeList::iterator it2;
00483 while( it != m_attribs->end() )
00484 {
00485 it2 = it++;
00486 delete (*it2);
00487 m_attribs->erase( it2 );
00488 }
00489
00490
00491 *m_attribs = attributes;
00492 }
00493
00494 AttributeList::iterator it = m_attribs->begin();
00495 for( ; it != m_attribs->end(); ++it )
00496 (*it)->m_parent = this;
00497 }
00498
00499 void Tag::addChild( Tag* child )
00500 {
00501 if( !child )
00502 return;
00503
00504 if( !m_nodes )
00505 m_nodes = new NodeList();
00506 if( !m_children )
00507 m_children = new TagList();
00508
00509 m_children->push_back( child );
00510 child->m_parent = this;
00511 m_nodes->push_back( new Node( TypeTag, child ) );
00512 }
00513
00514 void Tag::addChildCopy( const Tag* child )
00515 {
00516 if( !child )
00517 return;
00518
00519 addChild( child->clone() );
00520 }
00521
00522 bool Tag::setCData( const std::string& cdata )
00523 {
00524 if( cdata.empty() || !util::checkValidXMLChars( cdata ) )
00525 return false;
00526
00527 if( !m_cdata )
00528 m_cdata = new StringPList();
00529 else
00530 {
00531
00532
00533 StringPList::iterator it = m_cdata->begin();
00534 StringPList::iterator it2;
00535 while( it != m_cdata->end() )
00536 {
00537 it2 = it++;
00538 delete (*it2);
00539 m_cdata->erase( it2 );
00540 }
00541
00542 }
00543
00544 if( !m_nodes )
00545 m_nodes = new NodeList();
00546 else
00547 {
00548 NodeList::iterator it = m_nodes->begin();
00549 NodeList::iterator t;
00550 while( it != m_nodes->end() )
00551 {
00552 if( (*it)->type == TypeString )
00553 {
00554 t = it++;
00555 delete (*t);
00556 m_nodes->erase( t );
00557 }
00558 }
00559 }
00560
00561 return addCData( cdata );
00562 }
00563
00564 bool Tag::addCData( const std::string& cdata )
00565 {
00566 if( cdata.empty() || !util::checkValidXMLChars( cdata ) )
00567 return false;
00568
00569 if( !m_cdata )
00570 m_cdata = new StringPList();
00571 if( !m_nodes )
00572 m_nodes = new NodeList();
00573
00574 std::string* str = new std::string( cdata );
00575 m_cdata->push_back( str );
00576 m_nodes->push_back( new Node( TypeString, str ) );
00577 return true;
00578 }
00579
00580 const std::string Tag::cdata() const
00581 {
00582 if( !m_cdata )
00583 return EmptyString;
00584
00585 std::string str;
00586 StringPList::const_iterator it = m_cdata->begin();
00587 for( ; it != m_cdata->end(); ++it )
00588 str += *(*it);
00589
00590 return str;
00591 }
00592
00593 const TagList& Tag::children() const
00594 {
00595 static const TagList empty;
00596 return m_children ? *m_children : empty;
00597 }
00598
00599 const Tag::AttributeList& Tag::attributes() const
00600 {
00601 static const AttributeList empty;
00602 return m_attribs ? *m_attribs : empty;
00603 }
00604
00605 bool Tag::setXmlns( const std::string& xmlns, const std::string& prefix )
00606 {
00607 if( !util::checkValidXMLChars( xmlns ) || !util::checkValidXMLChars( prefix ) )
00608 return false;
00609
00610 if( prefix.empty() )
00611 {
00612 m_xmlns = xmlns;
00613 return addAttribute( XMLNS, m_xmlns );
00614 }
00615 else
00616 {
00617 if( !m_xmlnss )
00618 m_xmlnss = new StringMap();
00619
00620 (*m_xmlnss)[prefix] = xmlns;
00621
00622 return addAttribute( XMLNS + ":" + prefix, xmlns );
00623 }
00624 }
00625
00626 const std::string& Tag::xmlns() const
00627 {
00628 return xmlns( m_prefix );
00629 }
00630
00631 const std::string& Tag::xmlns( const std::string& prefix ) const
00632 {
00633 if( prefix.empty() )
00634 {
00635 return hasAttribute( XMLNS ) ? findAttribute( XMLNS ) : m_xmlns;
00636 }
00637
00638 if( m_xmlnss )
00639 {
00640 StringMap::const_iterator it = m_xmlnss->find( prefix );
00641 if( it != m_xmlnss->end() )
00642 return (*it).second;
00643 }
00644
00645 return m_parent ? m_parent->xmlns( prefix ) : EmptyString;
00646 }
00647
00648 bool Tag::setPrefix( const std::string& prefix )
00649 {
00650 if( !util::checkValidXMLChars( prefix ) )
00651 return false;
00652
00653 m_prefix = prefix;
00654 return true;
00655 }
00656
00657 const std::string& Tag::prefix( const std::string& xmlns ) const
00658 {
00659 if( xmlns.empty() || !m_xmlnss )
00660 return EmptyString;
00661
00662 StringMap::const_iterator it = m_xmlnss->begin();
00663 for( ; it != m_xmlnss->end(); ++it )
00664 {
00665 if( (*it).second == xmlns )
00666 return (*it).first;
00667 }
00668
00669 return EmptyString;
00670 }
00671
00672 const std::string& Tag::findAttribute( const std::string& name ) const
00673 {
00674 if( !m_attribs )
00675 return EmptyString;
00676
00677 AttributeList::const_iterator it = m_attribs->begin();
00678 for( ; it != m_attribs->end(); ++it )
00679 if( (*it)->name() == name )
00680 return (*it)->value();
00681
00682 return EmptyString;
00683 }
00684
00685 bool Tag::hasAttribute( const std::string& name, const std::string& value ) const
00686 {
00687 if( name.empty() || !m_attribs )
00688 return false;
00689
00690 AttributeList::const_iterator it = m_attribs->begin();
00691 for( ; it != m_attribs->end(); ++it )
00692 if( (*it)->name() == name )
00693 return value.empty() || (*it)->value() == value;
00694
00695 return false;
00696 }
00697
00698 bool Tag::hasChild( const std::string& name, const std::string& attr,
00699 const std::string& value ) const
00700 {
00701 if( attr.empty() )
00702 return findChild( name ) ? true : false;
00703 else
00704 return findChild( name, attr, value ) ? true : false;
00705 }
00706
00707 Tag* Tag::findChild( const std::string& name ) const
00708 {
00709 if( !m_children )
00710 return 0;
00711
00712 TagList::const_iterator it = m_children->begin();
00713 while( it != m_children->end() && (*it)->name() != name )
00714 ++it;
00715 return it != m_children->end() ? (*it) : 0;
00716 }
00717
00718 Tag* Tag::findChild( const std::string& name, const std::string& attr,
00719 const std::string& value ) const
00720 {
00721 if( !m_children || name.empty() )
00722 return 0;
00723
00724 TagList::const_iterator it = m_children->begin();
00725 while( it != m_children->end() && ( (*it)->name() != name || !(*it)->hasAttribute( attr, value ) ) )
00726 ++it;
00727 return it != m_children->end() ? (*it) : 0;
00728 }
00729
00730 bool Tag::hasChildWithCData( const std::string& name, const std::string& cdata ) const
00731 {
00732 if( !m_children || name.empty() || cdata.empty() )
00733 return 0;
00734
00735 TagList::const_iterator it = m_children->begin();
00736 while( it != m_children->end() && ( (*it)->name() != name
00737 || ( !cdata.empty() && (*it)->cdata() != cdata ) ) )
00738 ++it;
00739 return it != m_children->end();
00740 }
00741
00742 Tag* Tag::findChildWithAttrib( const std::string& attr, const std::string& value ) const
00743 {
00744 if( !m_children || attr.empty() )
00745 return 0;
00746
00747 TagList::const_iterator it = m_children->begin();
00748 while( it != m_children->end() && !(*it)->hasAttribute( attr, value ) )
00749 ++it;
00750 return it != m_children->end() ? (*it) : 0;
00751 }
00752
00753 Tag* Tag::clone() const
00754 {
00755 Tag* t = new Tag( m_name );
00756 t->m_xmlns = m_xmlns;
00757 t->m_prefix = m_prefix;
00758
00759 if( m_attribs )
00760 {
00761 t->m_attribs = new AttributeList();
00762 Tag::AttributeList::const_iterator at = m_attribs->begin();
00763 Attribute* attr;
00764 for( ; at != m_attribs->end(); ++at )
00765 {
00766 attr = new Attribute( *(*at) );
00767 attr->m_parent = t;
00768 t->m_attribs->push_back( attr );
00769 }
00770 }
00771
00772 if( m_xmlnss )
00773 {
00774 t->m_xmlnss = new StringMap( *m_xmlnss );
00775 }
00776
00777 if( m_nodes )
00778 {
00779 Tag::NodeList::const_iterator nt = m_nodes->begin();
00780 for( ; nt != m_nodes->end(); ++nt )
00781 {
00782 switch( (*nt)->type )
00783 {
00784 case TypeTag:
00785 t->addChild( (*nt)->tag->clone() );
00786 break;
00787 case TypeString:
00788 t->addCData( *((*nt)->str) );
00789 break;
00790 }
00791 }
00792 }
00793
00794 return t;
00795 }
00796
00797 TagList Tag::findChildren( const std::string& name,
00798 const std::string& xmlns ) const
00799 {
00800 return m_children ? findChildren( *m_children, name, xmlns ) : TagList();
00801 }
00802
00803 TagList Tag::findChildren( const TagList& list, const std::string& name,
00804 const std::string& xmlns ) const
00805 {
00806 TagList ret;
00807 TagList::const_iterator it = list.begin();
00808 for( ; it != list.end(); ++it )
00809 {
00810 if( (*it)->name() == name && ( xmlns.empty() || (*it)->xmlns() == xmlns ) )
00811 ret.push_back( (*it) );
00812 }
00813 return ret;
00814 }
00815
00816 void Tag::removeChild( const std::string& name, const std::string& xmlns )
00817 {
00818 if( name.empty() || !m_children || !m_nodes )
00819 return;
00820
00821 TagList l = findChildren( name, xmlns );
00822 TagList::iterator it = l.begin();
00823 TagList::iterator it2;
00824 while( it != l.end() )
00825 {
00826 it2 = it++;
00827 NodeList::iterator itn = m_nodes->begin();
00828 for( ; itn != m_nodes->end(); ++itn )
00829 {
00830 if( (*itn)->type == TypeTag && (*itn)->tag == (*it2) )
00831 {
00832 delete (*itn);
00833 m_nodes->erase( itn );
00834 break;
00835 }
00836 }
00837 m_children->remove( (*it2) );
00838 delete (*it2);
00839 }
00840 }
00841
00842 void Tag::removeChild( Tag* tag )
00843 {
00844 if( m_children )
00845 m_children->remove( tag );
00846
00847 if( !m_nodes )
00848 return;
00849
00850 NodeList::iterator it = m_nodes->begin();
00851 for( ; it != m_nodes->end(); ++it )
00852 {
00853 if( (*it)->type == TypeTag && (*it)->tag == tag )
00854 {
00855 delete (*it);
00856 m_nodes->erase( it );
00857 return;
00858 }
00859 }
00860 }
00861
00862 void Tag::removeAttribute( const std::string& attr, const std::string& value,
00863 const std::string& xmlns )
00864 {
00865 if( attr.empty() || !m_attribs )
00866 return;
00867
00868 AttributeList::iterator it = m_attribs->begin();
00869 AttributeList::iterator it2;
00870 while( it != m_attribs->end() )
00871 {
00872 it2 = it++;
00873 if( (*it2)->name() == attr && ( value.empty() || (*it2)->value() == value )
00874 && ( xmlns.empty() || (*it2)->xmlns() == xmlns ) )
00875 {
00876 delete (*it2);
00877 m_attribs->erase( it2 );
00878 }
00879 }
00880 }
00881
00882 const std::string Tag::findCData( const std::string& expression ) const
00883 {
00884 const ConstTagList& l = findTagList( expression );
00885 return !l.empty() ? l.front()->cdata() : EmptyString;
00886 }
00887
00888 const Tag* Tag::findTag( const std::string& expression ) const
00889 {
00890 const ConstTagList& l = findTagList( expression );
00891 return !l.empty() ? l.front() : 0;
00892 }
00893
00894 ConstTagList Tag::findTagList( const std::string& expression ) const
00895 {
00896 ConstTagList l;
00897 if( expression == "/" || expression == "//" )
00898 return l;
00899
00900 if( m_parent && expression.length() >= 2 && expression[0] == '/'
00901 && expression[1] != '/' )
00902 return m_parent->findTagList( expression );
00903
00904 unsigned len = 0;
00905 Tag* p = parse( expression, len );
00906
00907
00908 l = evaluateTagList( p );
00909 delete p;
00910 return l;
00911 }
00912
00913 ConstTagList Tag::evaluateTagList( Tag* token ) const
00914 {
00915 ConstTagList result;
00916 if( !token )
00917 return result;
00918
00919
00920
00921
00922 TokenType tokenType = (TokenType)atoi( token->findAttribute( TYPE ).c_str() );
00923 switch( tokenType )
00924 {
00925 case XTUnion:
00926 add( result, evaluateUnion( token ) );
00927 break;
00928 case XTElement:
00929 {
00930
00931 if( token->name() == name() || token->name() == "*" )
00932 {
00933
00934 const TagList& tokenChildren = token->children();
00935 if( tokenChildren.size() )
00936 {
00937 bool predicatesSucceeded = true;
00938 TagList::const_iterator cit = tokenChildren.begin();
00939 for( ; cit != tokenChildren.end(); ++cit )
00940 {
00941 if( (*cit)->hasAttribute( "predicate", "true" ) )
00942 {
00943 predicatesSucceeded = evaluatePredicate( (*cit) );
00944 if( !predicatesSucceeded )
00945 return result;
00946 }
00947 }
00948
00949 bool hasElementChildren = false;
00950 cit = tokenChildren.begin();
00951 for( ; cit != tokenChildren.end(); ++cit )
00952 {
00953 if( (*cit)->hasAttribute( "predicate", "true" ) ||
00954 (*cit)->hasAttribute( "number", "true" ) )
00955 continue;
00956
00957 hasElementChildren = true;
00958
00959
00960 if( m_children && !m_children->empty() )
00961 {
00962 TagList::const_iterator it = m_children->begin();
00963 for( ; it != m_children->end(); ++it )
00964 {
00965 add( result, (*it)->evaluateTagList( (*cit) ) );
00966 }
00967 }
00968 else if( atoi( (*cit)->findAttribute( TYPE ).c_str() ) == XTDoubleDot && m_parent )
00969 {
00970 (*cit)->addAttribute( TYPE, XTDot );
00971 add( result, m_parent->evaluateTagList( (*cit) ) );
00972 }
00973 }
00974
00975 if( !hasElementChildren )
00976 result.push_back( this );
00977 }
00978 else
00979 {
00980
00981 result.push_back( this );
00982 }
00983 }
00984
00985
00986
00987 break;
00988 }
00989 case XTDoubleSlash:
00990 {
00991
00992 Tag* t = token->clone();
00993
00994 t->addAttribute( TYPE, XTElement );
00995 add( result, evaluateTagList( t ) );
00996 const ConstTagList& res2 = allDescendants();
00997 ConstTagList::const_iterator it = res2.begin();
00998 for( ; it != res2.end(); ++it )
00999 {
01000 add( result, (*it)->evaluateTagList( t ) );
01001 }
01002 delete t;
01003 break;
01004 }
01005 case XTDot:
01006 {
01007 const TagList& tokenChildren = token->children();
01008 if( !tokenChildren.empty() )
01009 {
01010 add( result, evaluateTagList( tokenChildren.front() ) );
01011 }
01012 else
01013 result.push_back( this );
01014 break;
01015 }
01016 case XTDoubleDot:
01017 {
01018
01019 if( m_parent )
01020 {
01021 const TagList& tokenChildren = token->children();
01022 if( tokenChildren.size() )
01023 {
01024 Tag* testtoken = tokenChildren.front();
01025 if( testtoken->name() == "*" )
01026 {
01027 add( result, m_parent->evaluateTagList( testtoken ) );
01028 }
01029 else
01030 {
01031 Tag* t = token->clone();
01032 t->addAttribute( TYPE, XTElement );
01033 t->m_name = m_parent->m_name;
01034 add( result, m_parent->evaluateTagList( t ) );
01035 delete t;
01036 }
01037 }
01038 else
01039 {
01040 result.push_back( m_parent );
01041 }
01042 }
01043 }
01044 case XTInteger:
01045 {
01046 const TagList& l = token->children();
01047 if( !l.size() )
01048 break;
01049
01050 const ConstTagList& res = evaluateTagList( l.front() );
01051
01052 int pos = atoi( token->name().c_str() );
01053
01054 if( pos > 0 && pos <= (int)res.size() )
01055 {
01056 ConstTagList::const_iterator it = res.begin();
01057 while ( --pos )
01058 {
01059 ++it;
01060 }
01061 result.push_back( *it );
01062 }
01063 break;
01064 }
01065 default:
01066 break;
01067 }
01068 return result;
01069 }
01070
01071 bool Tag::evaluateBoolean( Tag* token ) const
01072 {
01073 if( !token )
01074 return false;
01075
01076 bool result = false;
01077 TokenType tokenType = (TokenType)atoi( token->findAttribute( TYPE ).c_str() );
01078 switch( tokenType )
01079 {
01080 case XTAttribute:
01081 if( token->name() == "*" && m_attribs && m_attribs->size() )
01082 result = true;
01083 else
01084 result = hasAttribute( token->name() );
01085 break;
01086 case XTOperatorEq:
01087 result = evaluateEquals( token );
01088 break;
01089 case XTOperatorLt:
01090 break;
01091 case XTOperatorLtEq:
01092 break;
01093 case XTOperatorGtEq:
01094 break;
01095 case XTOperatorGt:
01096 break;
01097 case XTUnion:
01098 case XTElement:
01099 {
01100 Tag* t = new Tag( "." );
01101 t->addAttribute( TYPE, XTDot );
01102 t->addChild( token );
01103 result = !evaluateTagList( t ).empty();
01104 t->removeChild( token );
01105 delete t;
01106 break;
01107 }
01108 default:
01109 break;
01110 }
01111
01112 return result;
01113 }
01114
01115 bool Tag::evaluateEquals( Tag* token ) const
01116 {
01117 if( !token || token->children().size() != 2 )
01118 return false;
01119
01120 bool result = false;
01121 TagList::const_iterator it = token->children().begin();
01122 Tag* ch1 = (*it);
01123 Tag* ch2 = (*++it);
01124
01125 TokenType tt1 = (TokenType)atoi( ch1->findAttribute( TYPE ).c_str() );
01126 TokenType tt2 = (TokenType)atoi( ch2->findAttribute( TYPE ).c_str() );
01127 switch( tt1 )
01128 {
01129 case XTAttribute:
01130 switch( tt2 )
01131 {
01132 case XTInteger:
01133 case XTLiteral:
01134 result = ( findAttribute( ch1->name() ) == ch2->name() );
01135 break;
01136 case XTAttribute:
01137 result = ( hasAttribute( ch1->name() ) && hasAttribute( ch2->name() ) &&
01138 findAttribute( ch1->name() ) == findAttribute( ch2->name() ) );
01139 break;
01140 default:
01141 break;
01142 }
01143 break;
01144 case XTInteger:
01145 case XTLiteral:
01146 switch( tt2 )
01147 {
01148 case XTAttribute:
01149 result = ( ch1->name() == findAttribute( ch2->name() ) );
01150 break;
01151 case XTLiteral:
01152 case XTInteger:
01153 result = ( ch1->name() == ch2->name() );
01154 break;
01155 default:
01156 break;
01157 }
01158 break;
01159 default:
01160 break;
01161 }
01162
01163 return result;
01164 }
01165
01166 ConstTagList Tag::allDescendants() const
01167 {
01168 ConstTagList result;
01169
01170 if( !m_children )
01171 return result;
01172
01173 TagList::const_iterator it = m_children->begin();
01174 for( ; it != m_children->end(); ++it )
01175 {
01176 result.push_back( (*it) );
01177 add( result, (*it)->allDescendants() );
01178 }
01179 return result;
01180 }
01181
01182 ConstTagList Tag::evaluateUnion( Tag* token ) const
01183 {
01184 ConstTagList result;
01185 if( !token )
01186 return result;
01187
01188 const TagList& l = token->children();
01189 TagList::const_iterator it = l.begin();
01190 for( ; it != l.end(); ++it )
01191 {
01192 add( result, evaluateTagList( (*it) ) );
01193 }
01194 return result;
01195 }
01196
01197 void Tag::closePreviousToken( Tag** root, Tag** current, Tag::TokenType& type, std::string& tok ) const
01198 {
01199 if( !tok.empty() )
01200 {
01201 addToken( root, current, type, tok );
01202 type = XTElement;
01203 tok = EmptyString;
01204 }
01205 }
01206
01207 Tag* Tag::parse( const std::string& expression, unsigned& len, Tag::TokenType border ) const
01208 {
01209 Tag* root = 0;
01210 Tag* current = root;
01211 std::string token;
01212
01213
01214
01215
01216
01217
01218
01219 Tag::TokenType type = XTElement;
01220
01221 char c;
01222 for( ; len < expression.length(); ++len )
01223 {
01224 c = expression[len];
01225 if( type == XTLiteralInside && c != '\'' )
01226 {
01227 token += c;
01228 continue;
01229 }
01230
01231 switch( c )
01232 {
01233 case '/':
01234 closePreviousToken( &root, ¤t, type, token );
01235
01236 if( len < expression.length()-1 && expression[len+1] == '/' )
01237 {
01238
01239 type = XTDoubleSlash;
01240 ++len;
01241 }
01242
01243
01244
01245
01246
01247 break;
01248 case ']':
01249 closePreviousToken( &root, ¤t, type, token );
01250 return root;
01251 case '[':
01252 {
01253 closePreviousToken( &root, ¤t, type, token );
01254 Tag* t = parse( expression, ++len, XTRightBracket );
01255 if( !addPredicate( &root, ¤t, t ) )
01256 delete t;
01257 break;
01258 }
01259 case '(':
01260 {
01261 closePreviousToken( &root, ¤t, type, token );
01262 Tag* t = parse( expression, ++len, XTRightParenthesis );
01263 if( current )
01264 {
01265
01266 t->addAttribute( "argument", "true" );
01267 current->addChild( t );
01268 }
01269 else
01270 {
01271 root = t;
01272
01273 }
01274 break;
01275 }
01276 case ')':
01277 closePreviousToken( &root, ¤t, type, token );
01278 ++len;
01279 return root;
01280 case '\'':
01281 if( type == XTLiteralInside )
01282 if( expression[len - 2] == '\\' )
01283 token[token.length() - 2] = c;
01284 else
01285 type = XTLiteral;
01286 else
01287 type = XTLiteralInside;
01288 break;
01289 case '@':
01290 type = XTAttribute;
01291 break;
01292 case '.':
01293 token += c;
01294 if( token.size() == 1 )
01295 {
01296 if( len < expression.length()-1 && expression[len+1] == '.' )
01297 {
01298 type = XTDoubleDot;
01299 ++len;
01300 token += c;
01301 }
01302 else
01303 {
01304 type = XTDot;
01305 }
01306 }
01307 break;
01308 case '*':
01309
01310
01311
01312
01313
01314
01315 addToken( &root, ¤t, type, "*" );
01316 type = XTElement;
01317 break;
01318 case '+':
01319 case '>':
01320 case '<':
01321 case '=':
01322 case '|':
01323 {
01324 closePreviousToken( &root, ¤t, type, token );
01325 std::string s( 1, c );
01326 Tag::TokenType ttype = getType( s );
01327 if( ttype <= border )
01328 return root;
01329 Tag* t = parse( expression, ++len, ttype );
01330 addOperator( &root, ¤t, t, ttype, s );
01331 if( border == XTRightBracket )
01332 return root;
01333 break;
01334 }
01335 default:
01336 token += c;
01337 }
01338 }
01339
01340 if( !token.empty() )
01341 addToken( &root, ¤t, type, token );
01342
01343
01344
01345 return root;
01346 }
01347
01348 void Tag::addToken( Tag **root, Tag **current, Tag::TokenType type,
01349 const std::string& token ) const
01350 {
01351 Tag* t = new Tag( token );
01352 if( t->isNumber() && !t->children().size() )
01353 type = XTInteger;
01354 t->addAttribute( TYPE, type );
01355
01356 if( *root )
01357 {
01358
01359 (*current)->addChild( t );
01360 *current = t;
01361 }
01362 else
01363 {
01364
01365 *current = *root = t;
01366 }
01367 }
01368
01369 void Tag::addOperator( Tag** root, Tag** current, Tag* arg,
01370 Tag::TokenType type, const std::string& token ) const
01371 {
01372 Tag* t = new Tag( token );
01373 t->addAttribute( TYPE, type );
01374
01375
01376 t->addAttribute( "operator", "true" );
01377 t->addChild( *root );
01378 t->addChild( arg );
01379 *current = *root = t;
01380 }
01381
01382 bool Tag::addPredicate( Tag **root, Tag **current, Tag* token ) const
01383 {
01384 if( !*root || !*current )
01385 return false;
01386
01387 if( ( token->isNumber() && !token->children().size() ) || token->name() == "+" )
01388 {
01389
01390 if( !token->hasAttribute( "operator", "true" ) )
01391 {
01392 token->addAttribute( TYPE, XTInteger );
01393 }
01394 if( *root == *current )
01395 {
01396 *root = token;
01397
01398 }
01399 else
01400 {
01401 (*root)->removeChild( *current );
01402 (*root)->addChild( token );
01403
01404 }
01405 token->addChild( *current );
01406
01407 }
01408 else
01409 {
01410 token->addAttribute( "predicate", "true" );
01411 (*current)->addChild( token );
01412 }
01413
01414 return true;
01415 }
01416
01417 Tag::TokenType Tag::getType( const std::string& c )
01418 {
01419 if( c == "|" )
01420 return XTUnion;
01421 if( c == "<" )
01422 return XTOperatorLt;
01423 if( c == ">" )
01424 return XTOperatorGt;
01425 if( c == "*" )
01426 return XTOperatorMul;
01427 if( c == "+" )
01428 return XTOperatorPlus;
01429 if( c == "=" )
01430 return XTOperatorEq;
01431
01432 return XTNone;
01433 }
01434
01435 bool Tag::isWhitespace( const char c )
01436 {
01437 return ( c == 0x09 || c == 0x0a || c == 0x0d || c == 0x20 );
01438 }
01439
01440 bool Tag::isNumber() const
01441 {
01442 if( m_name.empty() )
01443 return false;
01444
01445 std::string::size_type l = m_name.length();
01446 std::string::size_type i = 0;
01447 while( i < l && isdigit( m_name[i] ) )
01448 ++i;
01449 return i == l;
01450 }
01451
01452 void Tag::add( ConstTagList& one, const ConstTagList& two )
01453 {
01454 ConstTagList::const_iterator it = two.begin();
01455 for( ; it != two.end(); ++it )
01456 if( std::find( one.begin(), one.end(), (*it) ) == one.end() )
01457 one.push_back( (*it) );
01458 }
01459
01460 }