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