XmlDoc.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "xmlpull/XmlDoc.h"
00022
00023
00024
00026
00028
00029 XmlNode_t::XmlNode_t( const std::string &p_name, size_t p_depth)
00030 {
00031 m_name = p_name;
00032 m_depth = p_depth;
00033
00034 m_empty = p_name.empty();
00035
00036 mp_parent = NULL;
00037 mp_prev = NULL;
00038 mp_next = NULL;
00039 }
00040
00041 XmlNode_t::XmlNode_t( const XmlNode_t &p_xmlNode)
00042 {
00043 *this = p_xmlNode;
00044 }
00045
00046 XmlNode_t &
00047 XmlNode_t::operator =( const XmlNode_t &p_xmlNode)
00048 {
00049 m_name = p_xmlNode.m_name;
00050 m_text = p_xmlNode.m_text;
00051 m_depth = p_xmlNode.m_depth;
00052
00053 m_empty = p_xmlNode.m_empty;
00054
00055 mp_parent = NULL;
00056 mp_prev = NULL;
00057 mp_next = NULL;
00058
00059 m_attributes = p_xmlNode.m_attributes;
00060 m_mapAttributes = p_xmlNode.m_mapAttributes;
00061
00062 m_mapNodes = p_xmlNode.m_mapNodes;
00063
00064 this->deallocateNodes();
00065
00066 for( size_t l_i = 0; l_i < p_xmlNode.m_nodes.size(); l_i++) {
00067
00068 XmlNode_t *l_tmpNode = new XmlNode_t( *( p_xmlNode.m_nodes[ l_i]));
00069
00070 l_tmpNode->setParent( this);
00071
00072 if( l_i > 0) {
00073 l_tmpNode->setPrev( m_nodes.back());
00074 m_nodes.back()->setNext( l_tmpNode);
00075 }
00076 m_nodes.push_back( l_tmpNode);
00077 }
00078
00079 return *this;
00080 }
00081
00082 XmlNode_t::~XmlNode_t()
00083 {
00084 this->deallocateNodes();
00085 }
00086
00087 void
00088 XmlNode_t::deallocateNodes( void)
00089 {
00090 for( size_t l_i = 0; l_i < m_nodes.size(); l_i++)
00091 delete m_nodes.at( l_i);
00092 m_nodes.clear();
00093 }
00094
00095 void
00096 XmlNode_t::clear( void)
00097 {
00098 m_name.clear();
00099 m_text.clear();
00100
00101 m_depth = 1;
00102
00103 m_empty = true;
00104
00105 mp_parent = NULL;
00106 mp_prev = NULL;
00107 mp_next = NULL;
00108
00109 m_attributes.clear();
00110 m_mapAttributes.clear();
00111
00112 this->deallocateNodes();
00113 m_mapNodes.clear();
00114 }
00115
00116 XmlNode_t &
00117 XmlNode_t::getParent( void) const
00118 {
00119 return *mp_parent;
00120 }
00121
00122 void
00123 XmlNode_t::setParent( XmlNode_t &p_parent)
00124 {
00125 mp_parent = &p_parent;
00126 }
00127
00128 void
00129 XmlNode_t::setParent( XmlNode_t *p_parent)
00130 {
00131 mp_parent = p_parent;
00132 }
00133
00134 XmlNode_t &
00135 XmlNode_t::getPrev( void) const
00136 {
00137 return *mp_prev;
00138 }
00139
00140 void
00141 XmlNode_t::setPrev( XmlNode_t &p_prev)
00142 {
00143 mp_prev = &p_prev;
00144 }
00145
00146 void
00147 XmlNode_t::setPrev( XmlNode_t *p_prev)
00148 {
00149 mp_prev = p_prev;
00150 }
00151
00152 XmlNode_t &
00153 XmlNode_t::getNext( void) const
00154 {
00155 return *mp_next;
00156 }
00157
00158 void
00159 XmlNode_t::setNext( XmlNode_t &p_next)
00160 {
00161 mp_next = &p_next;
00162 }
00163
00164 void
00165 XmlNode_t::setNext( XmlNode_t *p_next)
00166 {
00167 mp_next = p_next;
00168 }
00169
00170 const std::string &
00171 XmlNode_t::getName( void) const
00172 {
00173 return m_name;
00174 }
00175
00176 void
00177 XmlNode_t::setName( const std::string &p_name, bool p_empty)
00178 {
00179 m_name = p_name;
00180 m_empty = p_empty;
00181 }
00182
00183 const std::string &
00184 XmlNode_t::getText( void) const
00185 {
00186 return m_text;
00187 }
00188
00189 size_t
00190 XmlNode_t::getDepth( void) const
00191 {
00192 return m_depth;
00193 }
00194
00195 void
00196 XmlNode_t::setDepth( size_t p_depth)
00197 {
00198 m_depth = p_depth;
00199 }
00200
00201 bool
00202 XmlNode_t::isRootNode( void) const
00203 {
00204 return mp_parent == NULL;
00205 }
00206
00207 bool
00208 XmlNode_t::isTextNode( void) const
00209 {
00210 return m_nodes.empty();
00211 }
00212
00213 XmlNode_t &
00214 XmlNode_t::addNode( const std::string &p_name, bool p_empty)
00215 {
00216 XmlNode_t *l_xmlNode = new XmlNode_t( p_name);
00217 l_xmlNode->setEmpty( p_empty);
00218 return this->addNode( l_xmlNode);
00219 }
00220
00221 XmlNode_t &
00222 XmlNode_t::addNode( XmlNode_t *p_xmlNode)
00223 {
00224
00225 m_text.clear();
00226
00227 XmlNode_t *l_xmlNode = p_xmlNode;
00228
00229 if( l_xmlNode == NULL)
00230 l_xmlNode = new XmlNode_t();
00231
00232 l_xmlNode->setParent( this);
00233
00234 if( m_nodes.empty() == false) {
00235
00236 l_xmlNode->setPrev( m_nodes.back());
00237 m_nodes.back()->setNext( l_xmlNode);
00238
00239 }
00240
00241 l_xmlNode->setDepth( m_depth + 1);
00242 m_nodes.push_back( l_xmlNode);
00243
00244 m_mapNodes.insert( std::make_pair( l_xmlNode->getName(), m_nodes.size() - 1));
00245
00246 return *l_xmlNode;
00247 }
00248
00249 void
00250 XmlNode_t::addAttribute( const std::string &p_name, const std::string &p_value)
00251 {
00252 m_attributes.push_back( std::make_pair( p_name, p_value));
00253
00254 m_mapAttributes.insert( std::make_pair( p_name, m_attributes.size() - 1));
00255 }
00256
00257 bool
00258 XmlNode_t::getAttribute( const std::string &p_name, std::string &p_result) const
00259 {
00260 MapAttributes_t::const_iterator l_it = m_mapAttributes.find( p_name);
00261 if( l_it == m_mapAttributes.end())
00262 return false;
00263 size_t l_index = (*l_it).second;
00264 p_result = m_attributes[ l_index].second;
00265 return true;
00266 }
00267
00268 void
00269 XmlNode_t::setText( const std::string &p_text)
00270 {
00271 m_nodes.clear();
00272
00273 m_text = p_text;
00274 }
00275
00276 void
00277 XmlNode_t::setEmpty( bool p_empty)
00278 {
00279 m_empty = p_empty;
00280 }
00281
00282 bool
00283 XmlNode_t::empty( void) const
00284 {
00285 return m_empty;
00286 }
00287
00288 XmlNode_t *
00289 XmlNode_t::getNode( const std::string &p_name, size_t p_index) const
00290 {
00291
00292 std::pair<MultiMapNodes_t::const_iterator, MultiMapNodes_t::const_iterator> l_itRange;
00293 l_itRange = m_mapNodes.equal_range( p_name);
00294
00295 MultiMapNodes_t::const_iterator &l_itFirst = l_itRange.first;
00296 MultiMapNodes_t::const_iterator &l_itLast = l_itRange.second;
00297
00298 XmlNode_t *l_resultNode = NULL;
00299
00300 size_t l_index = 0;
00301
00302 while( l_itFirst != l_itLast) {
00303
00304 if( l_index == p_index) {
00305
00306 l_resultNode = m_nodes[ (*l_itFirst).second];
00307 break;
00308 }
00309 ++l_index;
00310 ++l_itFirst;
00311 }
00312
00313 return l_resultNode;
00314 }
00315
00316 void
00317 XmlNode_t::getAllChildren( XmlNode_t::VectorNodePtrs_t &p_children)
00318 {
00319 p_children = m_nodes;
00320 }
00321
00322 void
00323 XmlNode_t::findDirectChildren( const std::string &p_name, XmlNode_t::VectorNodePtrs_t &p_children)
00324 {
00325 for( size_t l_i = 0; l_i < m_nodes.size(); l_i++){
00326
00327 if( p_name == m_nodes[ l_i]->getName())
00328 p_children.push_back( m_nodes[ l_i]);
00329 }
00330 }
00331
00332 void
00333 XmlNode_t::findSelfOrChildren( const std::string &p_name, XmlNode_t::VectorNodePtrs_t &p_children, bool p_lazyRelativeMatch)
00334 {
00335
00336 if( m_name == p_name) {
00337 p_children.push_back( this);
00338 return;
00339 }
00340
00341 if( p_lazyRelativeMatch == true) {
00342
00343 for( size_t l_i = 0; l_i < m_nodes.size(); l_i++){
00344
00345 m_nodes[ l_i]->findSelfOrChildren( p_name, p_children, p_lazyRelativeMatch);
00346
00347 }
00348 }
00349 }
00350
00351 void
00352 XmlNode_t::findAny( const std::string &p_name, XmlNode_t::VectorNodePtrs_t &p_children)
00353 {
00354 if( m_name == p_name)
00355 p_children.push_back( this);
00356
00357 for( size_t l_i = 0; l_i < m_nodes.size(); l_i++){
00358
00359 m_nodes[ l_i]->findAny( p_name, p_children);
00360
00361 }
00362 }
00363
00364 bool
00365 XmlNode_t::operator ==( const XmlNode_t &p_xmlNode) const
00366 {
00367 return m_name == p_xmlNode.m_name;
00368 }
00369
00370 std::ostream &
00371 operator <<( std::ostream &p_ostream, const XmlNode_t &p_xmlNode)
00372 {
00373 p_ostream << std::string( ( p_xmlNode.m_depth - 1) * XmlNode_t::WS_AMOUNT, ' ');
00374
00375
00376 p_ostream << "<" << p_xmlNode.m_name;
00377
00378
00379 for( size_t l_i = 0; l_i < p_xmlNode.m_attributes.size(); l_i++) {
00380 p_ostream << " "
00381 << p_xmlNode.m_attributes[ l_i].first
00382 << "=\"" << p_xmlNode.m_attributes[ l_i].second
00383 << "\"";
00384 }
00385
00386 p_ostream << ">";
00387
00388
00389 if( p_xmlNode.isTextNode() == true) {
00390
00391 p_ostream << p_xmlNode.m_text;
00392 } else {
00393 p_ostream << std::endl;
00394 for( size_t l_i = 0; l_i < p_xmlNode.m_nodes.size(); l_i++) {
00395
00396 p_ostream << *( p_xmlNode.m_nodes[ l_i]);
00397 }
00398 }
00399
00400 if( p_xmlNode.isTextNode() == false)
00401 p_ostream << std::string( ( p_xmlNode.m_depth - 1)* XmlNode_t::WS_AMOUNT, ' ');
00402
00403
00404 p_ostream << "</" << p_xmlNode.m_name << ">" << std::endl;
00405
00406 return p_ostream;
00407 }
00408
00410
00412
00413 XmlDoc_t::XmlDoc_t( const XmlNode_t &p_xmlNode)
00414 {
00415 m_rootNode = p_xmlNode;
00416
00417 m_processEnvAndBody = false;
00418 m_lazyRelativeMatch = true;
00419 }
00420
00421 void
00422 XmlDoc_t::clear( void)
00423 {
00424
00425
00426 m_rootNode.clear();
00427 }
00428
00429 void
00430 XmlDoc_t::setProcessEnvAndBody( bool p_processEnvAndBody)
00431 {
00432 m_processEnvAndBody = p_processEnvAndBody;
00433 }
00434
00435 bool
00436 XmlDoc_t::getProcessEnvAndBody( void) const
00437 {
00438 return m_processEnvAndBody;
00439 }
00440
00441 void
00442 XmlDoc_t::setLazyRelativeMatch( bool p_lazyRelativeMatch)
00443 {
00444 m_lazyRelativeMatch = p_lazyRelativeMatch;
00445 }
00446
00447 bool
00448 XmlDoc_t::getLazyRelativeMatch( void) const
00449 {
00450 return m_lazyRelativeMatch;
00451 }
00452
00453 XmlNode_t &
00454 XmlDoc_t::setRootNode( const XmlNode_t &p_xmlNode)
00455 {
00456 m_rootNode = p_xmlNode;
00457 return m_rootNode;
00458 }
00459
00460 XmlNode_t &
00461 XmlDoc_t::getRootNode( void)
00462 {
00463 return m_rootNode;
00464 }
00465
00466 const XmlNode_t &
00467 XmlDoc_t::getRootNode( void) const
00468 {
00469 return m_rootNode;
00470 }
00471
00472 bool
00473 XmlDoc_t::xpath( const std::string &p_xpath, std::vector< std::string> &p_results, size_t p_index)
00474 {
00475
00476 std::vector< XmlNode_t *> l_nodeSet[ 2];
00477 size_t l_curSetIndex = 0;
00478
00479
00480
00481 if( m_processEnvAndBody == true) {
00482 l_nodeSet[ l_curSetIndex].push_back( &m_rootNode);
00483 } else {
00484
00485
00486
00487 XmlNode_t *l_tmpNode = m_rootNode.getNode( "Body");
00488
00489
00490
00491 if( l_tmpNode == NULL)
00492 return false;
00493
00494
00495 l_tmpNode->getAllChildren( l_nodeSet[ l_curSetIndex]);
00496
00497
00498 if( l_nodeSet[ l_curSetIndex].empty() == true)
00499 return false;
00500 }
00501
00502 std::string l_name, l_xpath;
00503 std::string::size_type l_slashPos = 0;
00504 std::string::size_type l_nonSlashPos = 0;
00505 size_t l_matchCounter = 0;
00506 bool l_matchAny = false;
00507 bool l_matchAttribute = false;
00508 bool l_lazyRelativeMatch = false;
00509
00510
00511 if( p_xpath.find( "/") == 0 && p_xpath.find( "//") != 0) {
00512
00513
00514 l_slashPos = p_xpath.find( "/", 1);
00515 l_name = p_xpath.substr( 1, l_slashPos - 1);
00516
00517
00518 for( size_t l_i = 0; l_i < l_nodeSet[ l_curSetIndex].size(); l_i++) {
00519
00520 XmlNode_t *l_tmpNode = l_nodeSet[ l_curSetIndex][ l_i];
00521
00522
00523 if( l_name == l_tmpNode->getName())
00524 l_nodeSet[ !l_curSetIndex].push_back( l_tmpNode);
00525 }
00526
00527
00528 l_curSetIndex = !l_curSetIndex;
00529
00530
00531
00532 if( l_nodeSet[ l_curSetIndex].empty() == true)
00533 return false;
00534
00535
00536 ++l_matchCounter;
00537 }
00538
00539
00540 l_xpath = p_xpath;
00541
00542
00543 while( l_slashPos != std::string::npos) {
00544
00545
00546 l_matchAny = false;
00547
00548
00549 l_lazyRelativeMatch = false;
00550
00551
00552 l_xpath = l_xpath.substr( l_slashPos);
00553
00554
00555 if( l_xpath.empty() == true)
00556 break;
00557
00558 l_slashPos = l_xpath.find( "/");
00559
00560 if( l_slashPos == 0) {
00561
00562
00563
00564
00565 if( l_xpath.find( "//") == 0)
00566 l_matchAny = true;
00567
00568
00569 l_nonSlashPos = l_xpath.find_first_not_of( "/");
00570
00571
00572
00573 if( l_nonSlashPos == std::string::npos)
00574 break;
00575
00576
00577 l_slashPos = l_xpath.find( "/", l_nonSlashPos);
00578
00579
00580 l_name = l_xpath.substr( l_nonSlashPos, l_slashPos - l_nonSlashPos);
00581
00582 } else {
00583
00584
00585
00586
00587 l_name = l_xpath.substr( 0, l_slashPos);
00588
00589
00590
00591 if( l_matchCounter == 0 && m_lazyRelativeMatch == true)
00592 l_lazyRelativeMatch = true;
00593 }
00594
00595
00596 ++l_matchCounter;
00597
00598
00599 if( l_name.empty() == true)
00600 break;
00601
00602
00603 if( l_name[ 0] == '@') {
00604
00605
00606 l_matchAttribute = true;
00607
00608 l_name = l_name.substr( 1);
00609
00610
00611
00612
00613 break;
00614 }
00615
00616
00617 l_nodeSet[ !l_curSetIndex].clear();
00618
00619 for( size_t l_i = 0; l_i < l_nodeSet[ l_curSetIndex].size(); l_i++) {
00620
00621 XmlNode_t *l_tmpNode = l_nodeSet[ l_curSetIndex][ l_i];
00622
00623
00624 if( l_matchAny == true)
00625 l_tmpNode->findAny( l_name, l_nodeSet[ !l_curSetIndex]);
00626
00627 else if( l_lazyRelativeMatch == true)
00628 l_tmpNode->findSelfOrChildren( l_name, l_nodeSet[ !l_curSetIndex], l_lazyRelativeMatch);
00629
00630 else
00631 l_tmpNode->findDirectChildren( l_name, l_nodeSet[ !l_curSetIndex]);
00632 }
00633
00634
00635 l_curSetIndex = !l_curSetIndex;
00636
00637
00638 if( l_nodeSet[ l_curSetIndex].empty() == true)
00639 return false;
00640 }
00641
00642
00643
00644 for( size_t l_i = 0; l_i < l_nodeSet[ l_curSetIndex].size(); l_i++) {
00645
00646 XmlNode_t *l_tmpNode = l_nodeSet[ l_curSetIndex][ l_i];
00647
00648
00649
00650
00651 if( p_index == 0 || ( l_i == ( p_index - 1))) {
00652
00653 if( l_matchAttribute == false) {
00654
00655 p_results.push_back( l_tmpNode->getText());
00656 } else {
00657
00658 std::string l_tmpAttr;
00659 if( l_tmpNode->getAttribute( l_name, l_tmpAttr) == true)
00660 p_results.push_back( l_tmpAttr);
00661 }
00662 }
00663 }
00664
00665
00666 return ( p_results.empty() == false);
00667 }
00668
00669 std::ostream &
00670 operator <<( std::ostream &p_ostream, const XmlDoc_t &p_xmlDoc)
00671 {
00672
00673 p_ostream << p_xmlDoc.m_rootNode;
00674
00675 return p_ostream;
00676 }
00677
00678