Plus  - Minimal XML for C++ (Version 0.9.2) Giancarlo Niccolai
Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

mxml_iterator.h

Go to the documentation of this file.
00001 /*
00002    Mini XML lib PLUS for C++
00003 
00004    Node::iterator class
00005 
00006    Author: Giancarlo Niccolai <gian@niccolai.ws>
00007 
00008    $Id: mxml_iterator.h,v 1.5 2004/04/10 23:50:25 jonnymind Exp $
00009 */
00010 
00011 //TO BE INCLUDED IN NODE.H
00012 
00013 //namespace MXML {
00014 
00015 template<class __Node >
00016 __iterator<__Node> &__iterator<__Node>::__prev()
00017 {
00018    assert( m_node != m_base );
00019 
00020    if (m_node == 0 ) {
00021       if ( m_base->parent() != 0 )
00022          m_node = m_base->parent()->lastChild();
00023       else {
00024          m_node = m_base;
00025          while ( m_node->next() != 0 )
00026             m_node = m_node->next();
00027       }
00028    }
00029    else
00030       m_node = m_node->prev();
00031    return *this;
00032 }
00033 
00034 template< class __Node >
00035 __iterator<__Node> &__iterator<__Node>::operator+=( int count )
00036 {
00037    while ( count != 0 && m_node != 0 )
00038       operator++();
00039    return *this;
00040 }
00041 
00042 template< class __Node >
00043 __iterator<__Node> &__iterator<__Node>::operator-=( int count )
00044 {
00045    while ( count != 0 && m_node != m_base )
00046       operator--();
00047    return *this;
00048 }
00049 
00050 template< class __Node >
00051 __iterator<__Node> __iterator<__Node>::operator+( int count )
00052 {
00053    __iterator tmp = *this;
00054    while ( count > 0 && tmp.m_node != 0 ) {
00055       operator++();
00056       count--;
00057    }
00058    return tmp;
00059 }
00060 
00061 template< class __Node >
00062 __iterator<__Node> __iterator<__Node>::operator-( int count )
00063 {
00064    __iterator tmp = *this;
00065    while ( count > 0 && tmp.m_node != m_base ) {
00066       operator--();
00067       count--;
00068    }
00069    return tmp;
00070 }
00071 
00072 /*********************************************
00073 * Deep iterator
00074 *********************************************/
00075 template< class __Node >
00076 __iterator<__Node> &__deep_iterator<__Node>::__next()
00077 {
00078    assert( m_node != 0 );
00079 
00080    if ( m_node->child() != 0 ) {
00081       m_node = m_node->child();
00082    }
00083    else if ( m_node->next() != 0 ) {
00084       m_node = m_node->next();
00085    }
00086    else {
00087       while ( m_node->parent() != 0 ) {
00088          m_node = m_node->parent();
00089          if ( m_node->next() != 0 )
00090             break;
00091       }
00092       m_node = m_node->next(); // can be NULL
00093    }
00094 
00095    return *this;
00096 }
00097 
00098 template< class __Node >
00099 __iterator<__Node> &__deep_iterator<__Node>::__prev()
00100 {
00101 return *this;
00102 }
00103 
00104 /***************************************************
00105 * Find iterator
00106 ***************************************************/
00107 template< class __Node >
00108 __find_iterator<__Node>::__find_iterator( __Node *nd ):
00109             __deep_iterator< __Node>( nd )
00110 {
00111    m_maxmatch = 0;
00112 }
00113 
00114 template< class __Node >
00115 __find_iterator<__Node>::__find_iterator( __Node *nd, std::string name, std::string attr,
00116                   std::string valatt, std::string data):
00117             __deep_iterator< __Node>( nd )
00118 {
00119    m_name = name;
00120    m_attr = attr;
00121    m_valattr = valatt;
00122    m_data = data;
00123    m_maxmatch = 0;
00124    if ( m_name != "" ) m_maxmatch++;
00125    if ( m_attr !=  "" ) m_maxmatch++;
00126    if ( m_valattr != "" ) m_maxmatch++;
00127    if ( m_data != "" ) m_maxmatch++;
00128    __find();
00129 };
00130 
00131 
00132 template< class __Node >
00133 __iterator<__Node> &__find_iterator<__Node>::__next()
00134 {
00135    __deep_iterator<__Node>::__next();
00136    return __find();
00137 }
00138 
00139 template< class __Node >
00140 __iterator<__Node> &__find_iterator<__Node>::__find()
00141 {
00142    int matches;
00143    while ( this->m_node != 0 ) {
00144       matches = 0;
00145       if ( m_name != "" && m_name == m_node->name() )
00146          matches++;
00147 
00148       if ( m_attr != "" && m_node->hasAttribute( m_attr ) ) {
00149          matches++;
00150          if ( m_valattr != "" && m_node->getAttribute( m_attr ) == m_valattr )
00151             matches++;
00152       }
00153 
00154       if ( m_data != "" && m_node->data().find( m_data ) != std::string::npos )
00155          matches++;
00156 
00157       if ( matches < m_maxmatch )
00158          __deep_iterator<__Node>::__next();
00159       else
00160          break;
00161    }
00162 
00163    return *this;
00164 }
00165 
00166 template< class __Node >
00167 __iterator<__Node> &__find_iterator<__Node>::__prev()
00168 {
00169 return *this;
00170 }
00171 
00172 
00173 /*********************************************
00174 * Path Iterator
00175 *********************************************/
00176 template< class __Node >
00177 __path_iterator<__Node>::__path_iterator( __Node *nd, std::string path ):
00178             __iterator< __Node>( nd )
00179 {
00180    m_path = path;
00181    __find();
00182 }
00183 
00184 template< class __Node >
00185 __iterator<__Node> &__path_iterator<__Node>::__next()
00186 {
00187    __Node *ptr = m_node;
00188    std::string name;
00189    std::string::size_type pos = m_path.rfind('/');
00190    
00191    if ( pos == std::string::npos ) {
00192       pos = 0;
00193       name = m_path;
00194    }
00195    else {
00196       pos++;
00197       name = m_path.substr( pos );
00198    }
00199    
00200    m_node = m_node->next();   
00201    // todo: this sucks, must re-do it better
00202    while ( m_node ) {
00203       if ( name == "*" || m_node->name() == name ) break;
00204       m_node = m_node->next();   
00205    }
00206    
00207    return *this;
00208 }
00209 
00210 template< class __Node >
00211 __iterator<__Node> &__path_iterator<__Node>::__prev()
00212 {
00213    assert( m_node != 0 );
00214 
00215    __Node *ptr = m_node;
00216    m_node = m_node->prev();
00217    // todo: this sucks, must re-do it better
00218    while ( m_node != 0 ) {
00219       if ( m_node->name() == ptr->name() ) break;
00220       m_node = m_node->prev();
00221    }
00222 
00223    return *this;
00224 }
00225 
00226 
00227 template< class __Node >
00228 __Node *__path_iterator<__Node>::subfind( __Node *parent, 
00229             std::string::size_type begin )
00230 {
00231    std::string::size_type end = m_path.find( '/', begin );
00232    std::string name = end == std::string::npos? m_path.substr( begin ) : m_path.substr( begin, end - begin );
00233    
00234    if ( name == "" ) return parent;
00235    
00236    parent = parent->child();
00237    while( parent != 0 ) {
00238       if ( name == "*"  || parent->name() == name ) {
00239          if ( end != std::string::npos ) {
00240             parent = subfind( parent, end +1 );
00241          }
00242          break;
00243       }
00244       parent = parent->next();
00245    }
00246    
00247    return parent;
00248 }
00249             
00250 template< class __Node >
00251 __iterator<__Node> &__path_iterator<__Node>::__find()
00252 {
00253    if ( m_node == 0 ) return *this;
00254    
00255    __Node *rootNode = m_node;
00256    std::string firstName;
00257    std::string::size_type pos;
00258    if ( rootNode->nodeType() == Node::typeDocument ) 
00259    {
00260       rootNode = rootNode->child();
00261       while( rootNode && rootNode->nodeType() != Node::typeTag )
00262          rootNode = rootNode->next();
00263       if ( ! rootNode )
00264       {
00265          m_node = 0;
00266          return *this;
00267       }
00268    }
00269    
00270    if ( m_path[0] == '/' ) 
00271    {         
00272       while( rootNode->parent() && rootNode->parent()->nodeType() != Node::typeDocument )
00273       {
00274          rootNode = rootNode->parent();
00275       }
00276       pos = m_path.find( '/', 1 );
00277       if( pos == std::string::npos ) 
00278          firstName = m_path.substr( 1 );
00279       else
00280          firstName = m_path.substr( 1, pos-1 );
00281    }
00282    else {
00283       // relative path, starting below us.
00284       rootNode = rootNode->child();
00285       pos = m_path.find( '/' );
00286       if( pos == std::string::npos ) 
00287          firstName = m_path;
00288       else
00289          firstName = m_path.substr( 0, pos );
00290    }
00291          
00292    while ( rootNode != 0 ) 
00293    {
00294       if ( firstName == "*" || firstName == rootNode->name() ) 
00295       {
00296          if ( pos == std::string::npos ) 
00297          {
00298             m_node = rootNode;
00299          }
00300          else {
00301             m_node = subfind( rootNode, pos+1 );
00302          }
00303          break;
00304       }
00305       rootNode = rootNode->next();
00306    }         
00307 
00308    return *this;
00309 }
00310 
00311 //}
00312 /* end of mxml_iterator.h */
00313 

Generated on Sun Apr 11 02:08:19 2004 for Mxml Plus by doxygen 1.3.5