1 /* 2 www.sourceforge.net/projects/tinyxml 3 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any 7 damages arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any 10 purpose, including commercial applications, and to alter it and 11 redistribute it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must 14 not claim that you wrote the original software. If you use this 15 software in a product, an acknowledgment in the product documentation 16 would be appreciated but is not required. 17 18 2. Altered source versions must be plainly marked as such, and 19 must not be misrepresented as being the original software. 20 21 3. This notice may not be removed or altered from any source 22 distribution. 23 */ 24 25 #include <ctype.h> 26 #include "tinyxml.h" 27 28 #ifdef TIXML_USE_STL 29 #include <sstream> 30 #endif 31 32 33 bool TiXmlBase::condenseWhiteSpace = true; 34 PutString(const TIXML_STRING & str,TIXML_OSTREAM * stream)35 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream ) 36 { 37 TIXML_STRING buffer; 38 PutString( str, &buffer ); 39 (*stream) << buffer; 40 } 41 PutString(const TIXML_STRING & str,TIXML_STRING * outString)42 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) 43 { 44 int i=0; 45 46 while( i<(int)str.length() ) 47 { 48 unsigned char c = (unsigned char) str[i]; 49 50 if ( c == '&' 51 && i < ( (int)str.length() - 2 ) 52 && str[i+1] == '#' 53 && str[i+2] == 'x' ) 54 { 55 // Hexadecimal character reference. 56 // Pass through unchanged. 57 // © -- copyright symbol, for example. 58 // 59 // The -1 is a bug fix from Rob Laveaux. It keeps 60 // an overflow from happening if there is no ';'. 61 // There are actually 2 ways to exit this loop - 62 // while fails (error case) and break (semicolon found). 63 // However, there is no mechanism (currently) for 64 // this function to return an error. 65 while ( i<(int)str.length()-1 ) 66 { 67 outString->append( str.c_str() + i, 1 ); 68 ++i; 69 if ( str[i] == ';' ) 70 break; 71 } 72 } 73 else if ( c == '&' ) 74 { 75 outString->append( entity[0].str, entity[0].strLength ); 76 ++i; 77 } 78 else if ( c == '<' ) 79 { 80 outString->append( entity[1].str, entity[1].strLength ); 81 ++i; 82 } 83 else if ( c == '>' ) 84 { 85 outString->append( entity[2].str, entity[2].strLength ); 86 ++i; 87 } 88 else if ( c == '\"' ) 89 { 90 outString->append( entity[3].str, entity[3].strLength ); 91 ++i; 92 } 93 else if ( c == '\'' ) 94 { 95 outString->append( entity[4].str, entity[4].strLength ); 96 ++i; 97 } 98 else if ( c < 32 ) 99 { 100 // Easy pass at non-alpha/numeric/symbol 101 // Below 32 is symbolic. 102 char buf[ 32 ]; 103 104 #if defined(TIXML_SNPRINTF) 105 TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); 106 #else 107 sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); 108 #endif 109 110 //*ME: warning C4267: convert 'size_t' to 'int' 111 //*ME: Int-Cast to make compiler happy ... 112 outString->append( buf, (int)strlen( buf ) ); 113 ++i; 114 } 115 else 116 { 117 //char realc = (char) c; 118 //outString->append( &realc, 1 ); 119 *outString += (char) c; // somewhat more efficient function call. 120 ++i; 121 } 122 } 123 } 124 125 126 // <-- Strange class for a bug fix. Search for STL_STRING_BUG StringToBuffer(const TIXML_STRING & str)127 TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str ) 128 { 129 buffer = new char[ str.length()+1 ]; 130 if ( buffer ) 131 { 132 strcpy( buffer, str.c_str() ); 133 } 134 } 135 136 ~StringToBuffer()137 TiXmlBase::StringToBuffer::~StringToBuffer() 138 { 139 delete [] buffer; 140 } 141 // End strange bug fix. --> 142 143 TiXmlNode(NodeType _type)144 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() 145 { 146 parent = 0; 147 type = _type; 148 firstChild = 0; 149 lastChild = 0; 150 prev = 0; 151 next = 0; 152 } 153 154 ~TiXmlNode()155 TiXmlNode::~TiXmlNode() 156 { 157 TiXmlNode* node = firstChild; 158 TiXmlNode* temp = 0; 159 160 while ( node ) 161 { 162 temp = node; 163 node = node->next; 164 delete temp; 165 } 166 } 167 168 CopyTo(TiXmlNode * target) const169 void TiXmlNode::CopyTo( TiXmlNode* target ) const 170 { 171 target->SetValue (value.c_str() ); 172 target->userData = userData; 173 } 174 175 Clear()176 void TiXmlNode::Clear() 177 { 178 TiXmlNode* node = firstChild; 179 TiXmlNode* temp = 0; 180 181 while ( node ) 182 { 183 temp = node; 184 node = node->next; 185 delete temp; 186 } 187 188 firstChild = 0; 189 lastChild = 0; 190 } 191 192 LinkEndChild(TiXmlNode * node)193 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) 194 { 195 node->parent = this; 196 197 node->prev = lastChild; 198 node->next = 0; 199 200 if ( lastChild ) 201 lastChild->next = node; 202 else 203 firstChild = node; // it was an empty list. 204 205 lastChild = node; 206 return node; 207 } 208 209 InsertEndChild(const TiXmlNode & addThis)210 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) 211 { 212 TiXmlNode* node = addThis.Clone(); 213 if ( !node ) 214 return 0; 215 216 return LinkEndChild( node ); 217 } 218 219 InsertBeforeChild(TiXmlNode * beforeThis,const TiXmlNode & addThis)220 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) 221 { 222 if ( !beforeThis || beforeThis->parent != this ) 223 return 0; 224 225 TiXmlNode* node = addThis.Clone(); 226 if ( !node ) 227 return 0; 228 node->parent = this; 229 230 node->next = beforeThis; 231 node->prev = beforeThis->prev; 232 if ( beforeThis->prev ) 233 { 234 beforeThis->prev->next = node; 235 } 236 else 237 { 238 assert( firstChild == beforeThis ); 239 firstChild = node; 240 } 241 beforeThis->prev = node; 242 return node; 243 } 244 245 InsertAfterChild(TiXmlNode * afterThis,const TiXmlNode & addThis)246 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) 247 { 248 if ( !afterThis || afterThis->parent != this ) 249 return 0; 250 251 TiXmlNode* node = addThis.Clone(); 252 if ( !node ) 253 return 0; 254 node->parent = this; 255 256 node->prev = afterThis; 257 node->next = afterThis->next; 258 if ( afterThis->next ) 259 { 260 afterThis->next->prev = node; 261 } 262 else 263 { 264 assert( lastChild == afterThis ); 265 lastChild = node; 266 } 267 afterThis->next = node; 268 return node; 269 } 270 271 ReplaceChild(TiXmlNode * replaceThis,const TiXmlNode & withThis)272 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) 273 { 274 if ( replaceThis->parent != this ) 275 return 0; 276 277 TiXmlNode* node = withThis.Clone(); 278 if ( !node ) 279 return 0; 280 281 node->next = replaceThis->next; 282 node->prev = replaceThis->prev; 283 284 if ( replaceThis->next ) 285 replaceThis->next->prev = node; 286 else 287 lastChild = node; 288 289 if ( replaceThis->prev ) 290 replaceThis->prev->next = node; 291 else 292 firstChild = node; 293 294 delete replaceThis; 295 node->parent = this; 296 return node; 297 } 298 299 RemoveChild(TiXmlNode * removeThis)300 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) 301 { 302 if ( removeThis->parent != this ) 303 { 304 assert( 0 ); 305 return false; 306 } 307 308 if ( removeThis->next ) 309 removeThis->next->prev = removeThis->prev; 310 else 311 lastChild = removeThis->prev; 312 313 if ( removeThis->prev ) 314 removeThis->prev->next = removeThis->next; 315 else 316 firstChild = removeThis->next; 317 318 delete removeThis; 319 return true; 320 } 321 FirstChild(const char * _value) const322 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const 323 { 324 const TiXmlNode* node; 325 for ( node = firstChild; node; node = node->next ) 326 { 327 if ( strcmp( node->Value(), _value ) == 0 ) 328 return node; 329 } 330 return 0; 331 } 332 333 FirstChild(const char * _value)334 TiXmlNode* TiXmlNode::FirstChild( const char * _value ) 335 { 336 TiXmlNode* node; 337 for ( node = firstChild; node; node = node->next ) 338 { 339 if ( strcmp( node->Value(), _value ) == 0 ) 340 return node; 341 } 342 return 0; 343 } 344 345 LastChild(const char * _value) const346 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const 347 { 348 const TiXmlNode* node; 349 for ( node = lastChild; node; node = node->prev ) 350 { 351 if ( strcmp( node->Value(), _value ) == 0 ) 352 return node; 353 } 354 return 0; 355 } 356 LastChild(const char * _value)357 TiXmlNode* TiXmlNode::LastChild( const char * _value ) 358 { 359 TiXmlNode* node; 360 for ( node = lastChild; node; node = node->prev ) 361 { 362 if ( strcmp( node->Value(), _value ) == 0 ) 363 return node; 364 } 365 return 0; 366 } 367 IterateChildren(const TiXmlNode * previous) const368 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const 369 { 370 if ( !previous ) 371 { 372 return FirstChild(); 373 } 374 else 375 { 376 assert( previous->parent == this ); 377 return previous->NextSibling(); 378 } 379 } 380 IterateChildren(TiXmlNode * previous)381 TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) 382 { 383 if ( !previous ) 384 { 385 return FirstChild(); 386 } 387 else 388 { 389 assert( previous->parent == this ); 390 return previous->NextSibling(); 391 } 392 } 393 IterateChildren(const char * val,const TiXmlNode * previous) const394 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const 395 { 396 if ( !previous ) 397 { 398 return FirstChild( val ); 399 } 400 else 401 { 402 assert( previous->parent == this ); 403 return previous->NextSibling( val ); 404 } 405 } 406 IterateChildren(const char * val,TiXmlNode * previous)407 TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) 408 { 409 if ( !previous ) 410 { 411 return FirstChild( val ); 412 } 413 else 414 { 415 assert( previous->parent == this ); 416 return previous->NextSibling( val ); 417 } 418 } 419 NextSibling(const char * _value) const420 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 421 { 422 const TiXmlNode* node; 423 for ( node = next; node; node = node->next ) 424 { 425 if ( strcmp( node->Value(), _value ) == 0 ) 426 return node; 427 } 428 return 0; 429 } 430 NextSibling(const char * _value)431 TiXmlNode* TiXmlNode::NextSibling( const char * _value ) 432 { 433 TiXmlNode* node; 434 for ( node = next; node; node = node->next ) 435 { 436 if ( strcmp( node->Value(), _value ) == 0 ) 437 return node; 438 } 439 return 0; 440 } 441 PreviousSibling(const char * _value) const442 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const 443 { 444 const TiXmlNode* node; 445 for ( node = prev; node; node = node->prev ) 446 { 447 if ( strcmp( node->Value(), _value ) == 0 ) 448 return node; 449 } 450 return 0; 451 } 452 PreviousSibling(const char * _value)453 TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) 454 { 455 TiXmlNode* node; 456 for ( node = prev; node; node = node->prev ) 457 { 458 if ( strcmp( node->Value(), _value ) == 0 ) 459 return node; 460 } 461 return 0; 462 } 463 RemoveAttribute(const char * name)464 void TiXmlElement::RemoveAttribute( const char * name ) 465 { 466 TiXmlAttribute* node = attributeSet.Find( name ); 467 if ( node ) 468 { 469 attributeSet.Remove( node ); 470 delete node; 471 } 472 } 473 FirstChildElement() const474 const TiXmlElement* TiXmlNode::FirstChildElement() const 475 { 476 const TiXmlNode* node; 477 478 for ( node = FirstChild(); 479 node; 480 node = node->NextSibling() ) 481 { 482 if ( node->ToElement() ) 483 return node->ToElement(); 484 } 485 return 0; 486 } 487 FirstChildElement()488 TiXmlElement* TiXmlNode::FirstChildElement() 489 { 490 TiXmlNode* node; 491 492 for ( node = FirstChild(); 493 node; 494 node = node->NextSibling() ) 495 { 496 if ( node->ToElement() ) 497 return node->ToElement(); 498 } 499 return 0; 500 } 501 FirstChildElement(const char * _value) const502 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const 503 { 504 const TiXmlNode* node; 505 506 for ( node = FirstChild( _value ); 507 node; 508 node = node->NextSibling( _value ) ) 509 { 510 if ( node->ToElement() ) 511 return node->ToElement(); 512 } 513 return 0; 514 } 515 FirstChildElement(const char * _value)516 TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) 517 { 518 TiXmlNode* node; 519 520 for ( node = FirstChild( _value ); 521 node; 522 node = node->NextSibling( _value ) ) 523 { 524 if ( node->ToElement() ) 525 return node->ToElement(); 526 } 527 return 0; 528 } 529 NextSiblingElement() const530 const TiXmlElement* TiXmlNode::NextSiblingElement() const 531 { 532 const TiXmlNode* node; 533 534 for ( node = NextSibling(); 535 node; 536 node = node->NextSibling() ) 537 { 538 if ( node->ToElement() ) 539 return node->ToElement(); 540 } 541 return 0; 542 } 543 NextSiblingElement()544 TiXmlElement* TiXmlNode::NextSiblingElement() 545 { 546 TiXmlNode* node; 547 548 for ( node = NextSibling(); 549 node; 550 node = node->NextSibling() ) 551 { 552 if ( node->ToElement() ) 553 return node->ToElement(); 554 } 555 return 0; 556 } 557 NextSiblingElement(const char * _value) const558 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const 559 { 560 const TiXmlNode* node; 561 562 for ( node = NextSibling( _value ); 563 node; 564 node = node->NextSibling( _value ) ) 565 { 566 if ( node->ToElement() ) 567 return node->ToElement(); 568 } 569 return 0; 570 } 571 NextSiblingElement(const char * _value)572 TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) 573 { 574 TiXmlNode* node; 575 576 for ( node = NextSibling( _value ); 577 node; 578 node = node->NextSibling( _value ) ) 579 { 580 if ( node->ToElement() ) 581 return node->ToElement(); 582 } 583 return 0; 584 } 585 586 GetDocument() const587 const TiXmlDocument* TiXmlNode::GetDocument() const 588 { 589 const TiXmlNode* node; 590 591 for( node = this; node; node = node->parent ) 592 { 593 if ( node->ToDocument() ) 594 return node->ToDocument(); 595 } 596 return 0; 597 } 598 GetDocument()599 TiXmlDocument* TiXmlNode::GetDocument() 600 { 601 TiXmlNode* node; 602 603 for( node = this; node; node = node->parent ) 604 { 605 if ( node->ToDocument() ) 606 return node->ToDocument(); 607 } 608 return 0; 609 } 610 TiXmlElement(const char * _value)611 TiXmlElement::TiXmlElement (const char * _value) 612 : TiXmlNode( TiXmlNode::ELEMENT ) 613 { 614 firstChild = lastChild = 0; 615 value = _value; 616 } 617 618 619 #ifdef TIXML_USE_STL TiXmlElement(const std::string & _value)620 TiXmlElement::TiXmlElement( const std::string& _value ) 621 : TiXmlNode( TiXmlNode::ELEMENT ) 622 { 623 firstChild = lastChild = 0; 624 value = _value; 625 } 626 #endif 627 628 TiXmlElement(const TiXmlElement & copy)629 TiXmlElement::TiXmlElement( const TiXmlElement& copy) 630 : TiXmlNode( TiXmlNode::ELEMENT ) 631 { 632 firstChild = lastChild = 0; 633 copy.CopyTo( this ); 634 } 635 636 operator =(const TiXmlElement & base)637 void TiXmlElement::operator=( const TiXmlElement& base ) 638 { 639 ClearThis(); 640 base.CopyTo( this ); 641 } 642 643 ~TiXmlElement()644 TiXmlElement::~TiXmlElement() 645 { 646 ClearThis(); 647 } 648 649 ClearThis()650 void TiXmlElement::ClearThis() 651 { 652 Clear(); 653 while( attributeSet.First() ) 654 { 655 TiXmlAttribute* node = attributeSet.First(); 656 attributeSet.Remove( node ); 657 delete node; 658 } 659 } 660 661 Attribute(const char * name) const662 const char * TiXmlElement::Attribute( const char * name ) const 663 { 664 const TiXmlAttribute* node = attributeSet.Find( name ); 665 666 if ( node ) 667 return node->Value(); 668 669 return 0; 670 } 671 672 Attribute(const char * name,int * i) const673 const char * TiXmlElement::Attribute( const char * name, int* i ) const 674 { 675 const char * s = Attribute( name ); 676 if ( i ) 677 { 678 if ( s ) 679 *i = atoi( s ); 680 else 681 *i = 0; 682 } 683 return s; 684 } 685 686 Attribute(const char * name,double * d) const687 const char * TiXmlElement::Attribute( const char * name, double* d ) const 688 { 689 const char * s = Attribute( name ); 690 if ( d ) 691 { 692 if ( s ) 693 *d = atof( s ); 694 else 695 *d = 0; 696 } 697 return s; 698 } 699 700 QueryIntAttribute(const char * name,int * ival) const701 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const 702 { 703 const TiXmlAttribute* node = attributeSet.Find( name ); 704 if ( !node ) 705 return TIXML_NO_ATTRIBUTE; 706 707 return node->QueryIntValue( ival ); 708 } 709 710 QueryDoubleAttribute(const char * name,double * dval) const711 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const 712 { 713 const TiXmlAttribute* node = attributeSet.Find( name ); 714 if ( !node ) 715 return TIXML_NO_ATTRIBUTE; 716 717 return node->QueryDoubleValue( dval ); 718 } 719 720 SetAttribute(const char * name,int val)721 void TiXmlElement::SetAttribute( const char * name, int val ) 722 { 723 char buf[64]; 724 #if defined(TIXML_SNPRINTF) 725 TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); 726 #else 727 sprintf( buf, "%d", val ); 728 #endif 729 SetAttribute( name, buf ); 730 } 731 732 SetDoubleAttribute(const char * name,double val)733 void TiXmlElement::SetDoubleAttribute( const char * name, double val ) 734 { 735 char buf[256]; 736 #if defined(TIXML_SNPRINTF) 737 TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); 738 #else 739 sprintf( buf, "%f", val ); 740 #endif 741 SetAttribute( name, buf ); 742 } 743 744 SetAttribute(const char * name,const char * _value)745 void TiXmlElement::SetAttribute( const char * name, const char * _value ) 746 { 747 TiXmlAttribute* node = attributeSet.Find( name ); 748 if ( node ) 749 { 750 node->SetValue( _value ); 751 return; 752 } 753 754 TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); 755 if ( attrib ) 756 { 757 attributeSet.Add( attrib ); 758 } 759 else 760 { 761 TiXmlDocument* document = GetDocument(); 762 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); 763 } 764 } 765 Print(FILE * cfile,int depth) const766 void TiXmlElement::Print( FILE* cfile, int depth ) const 767 { 768 int i; 769 for ( i=0; i<depth; i++ ) 770 { 771 fprintf( cfile, " " ); 772 } 773 774 fprintf( cfile, "<%s", value.c_str() ); 775 776 const TiXmlAttribute* attrib; 777 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) 778 { 779 fprintf( cfile, " " ); 780 attrib->Print( cfile, depth ); 781 } 782 783 // There are 3 different formatting approaches: 784 // 1) An element without children is printed as a <foo /> node 785 // 2) An element with only a text child is printed as <foo> text </foo> 786 // 3) An element with children is printed on multiple lines. 787 TiXmlNode* node; 788 if ( !firstChild ) 789 { 790 fprintf( cfile, " />" ); 791 } 792 else if ( firstChild == lastChild && firstChild->ToText() ) 793 { 794 fprintf( cfile, ">" ); 795 firstChild->Print( cfile, depth + 1 ); 796 fprintf( cfile, "</%s>", value.c_str() ); 797 } 798 else 799 { 800 fprintf( cfile, ">" ); 801 802 for ( node = firstChild; node; node=node->NextSibling() ) 803 { 804 if ( !node->ToText() ) 805 { 806 fprintf( cfile, "\n" ); 807 } 808 node->Print( cfile, depth+1 ); 809 } 810 fprintf( cfile, "\n" ); 811 for( i=0; i<depth; ++i ) 812 fprintf( cfile, " " ); 813 fprintf( cfile, "</%s>", value.c_str() ); 814 } 815 } 816 StreamOut(TIXML_OSTREAM * stream) const817 void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const 818 { 819 (*stream) << "<" << value; 820 821 const TiXmlAttribute* attrib; 822 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) 823 { 824 (*stream) << " "; 825 attrib->StreamOut( stream ); 826 } 827 828 // If this node has children, give it a closing tag. Else 829 // make it an empty tag. 830 TiXmlNode* node; 831 if ( firstChild ) 832 { 833 (*stream) << ">"; 834 835 for ( node = firstChild; node; node=node->NextSibling() ) 836 { 837 node->StreamOut( stream ); 838 } 839 (*stream) << "</" << value << ">"; 840 } 841 else 842 { 843 (*stream) << " />"; 844 } 845 } 846 847 CopyTo(TiXmlElement * target) const848 void TiXmlElement::CopyTo( TiXmlElement* target ) const 849 { 850 // superclass: 851 TiXmlNode::CopyTo( target ); 852 853 // Element class: 854 // Clone the attributes, then clone the children. 855 const TiXmlAttribute* attribute = 0; 856 for( attribute = attributeSet.First(); 857 attribute; 858 attribute = attribute->Next() ) 859 { 860 target->SetAttribute( attribute->Name(), attribute->Value() ); 861 } 862 863 TiXmlNode* node = 0; 864 for ( node = firstChild; node; node = node->NextSibling() ) 865 { 866 target->LinkEndChild( node->Clone() ); 867 } 868 } 869 870 Clone() const871 TiXmlNode* TiXmlElement::Clone() const 872 { 873 TiXmlElement* clone = new TiXmlElement( Value() ); 874 if ( !clone ) 875 return 0; 876 877 CopyTo( clone ); 878 return clone; 879 } 880 881 GetText() const882 const char* TiXmlElement::GetText() const 883 { 884 const TiXmlNode* child = this->FirstChild(); 885 if ( child ) { 886 const TiXmlText* childText = child->ToText(); 887 if ( childText ) { 888 return childText->Value(); 889 } 890 } 891 return 0; 892 } 893 894 TiXmlDocument()895 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) 896 { 897 tabsize = 4; 898 useMicrosoftBOM = false; 899 ClearError(); 900 } 901 TiXmlDocument(const char * documentName)902 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 903 { 904 tabsize = 4; 905 useMicrosoftBOM = false; 906 value = documentName; 907 ClearError(); 908 } 909 910 911 #ifdef TIXML_USE_STL TiXmlDocument(const std::string & documentName)912 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 913 { 914 tabsize = 4; 915 useMicrosoftBOM = false; 916 value = documentName; 917 ClearError(); 918 } 919 #endif 920 921 TiXmlDocument(const TiXmlDocument & copy)922 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) 923 { 924 copy.CopyTo( this ); 925 } 926 927 operator =(const TiXmlDocument & copy)928 void TiXmlDocument::operator=( const TiXmlDocument& copy ) 929 { 930 Clear(); 931 copy.CopyTo( this ); 932 } 933 934 LoadFile(TiXmlEncoding encoding)935 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) 936 { 937 // See STL_STRING_BUG below. 938 StringToBuffer buf( value ); 939 940 if ( buf.buffer && LoadFile( buf.buffer, encoding ) ) 941 return true; 942 943 return false; 944 } 945 946 SaveFile() const947 bool TiXmlDocument::SaveFile() const 948 { 949 // See STL_STRING_BUG below. 950 StringToBuffer buf( value ); 951 952 if ( buf.buffer && SaveFile( buf.buffer ) ) 953 return true; 954 955 return false; 956 } 957 LoadFile(const char * filename,TiXmlEncoding encoding)958 bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding ) 959 { 960 // Delete the existing data: 961 Clear(); 962 location.Clear(); 963 964 // There was a really terrifying little bug here. The code: 965 // value = filename 966 // in the STL case, cause the assignment method of the std::string to 967 // be called. What is strange, is that the std::string had the same 968 // address as it's c_str() method, and so bad things happen. Looks 969 // like a bug in the Microsoft STL implementation. 970 // See STL_STRING_BUG above. 971 // Fixed with the StringToBuffer class. 972 value = filename; 973 974 // reading in binary mode so that tinyxml can normalize the EOL 975 FILE* file = fopen( value.c_str (), "rb" ); 976 977 if ( file ) 978 { 979 // Get the file size, so we can pre-allocate the string. HUGE speed impact. 980 long length = 0; 981 fseek( file, 0, SEEK_END ); 982 length = ftell( file ); 983 fseek( file, 0, SEEK_SET ); 984 985 // Strange case, but good to handle up front. 986 if ( length == 0 ) 987 { 988 fclose( file ); 989 return false; 990 } 991 992 // If we have a file, assume it is all one big XML file, and read it in. 993 // The document parser may decide the document ends sooner than the entire file, however. 994 TIXML_STRING data; 995 data.reserve( length ); 996 997 // Subtle bug here. TinyXml did use fgets. But from the XML spec: 998 // 2.11 End-of-Line Handling 999 // <snip> 1000 // <quote> 1001 // ...the XML processor MUST behave as if it normalized all line breaks in external 1002 // parsed entities (including the document entity) on input, before parsing, by translating 1003 // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 1004 // a single #xA character. 1005 // </quote> 1006 // 1007 // It is not clear fgets does that, and certainly isn't clear it works cross platform. 1008 // Generally, you expect fgets to translate from the convention of the OS to the c/unix 1009 // convention, and not work generally. 1010 1011 /* 1012 while( fgets( buf, sizeof(buf), file ) ) 1013 { 1014 data += buf; 1015 } 1016 */ 1017 1018 char* buf = new char[ length+1 ]; 1019 buf[0] = 0; 1020 1021 if ( fread( buf, length, 1, file ) != 1 ) { 1022 //if ( fread( buf, 1, length, file ) != (size_t)length ) { 1023 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 1024 fclose( file ); 1025 return false; 1026 } 1027 fclose( file ); 1028 1029 const char* lastPos = buf; 1030 const char* p = buf; 1031 1032 buf[length] = 0; 1033 while( *p ) { 1034 assert( p < (buf+length) ); 1035 if ( *p == 0xa ) { 1036 // Newline character. No special rules for this. Append all the characters 1037 // since the last string, and include the newline. 1038 data.append( lastPos, p-lastPos+1 ); // append, include the newline 1039 ++p; // move past the newline 1040 lastPos = p; // and point to the new buffer (may be 0) 1041 assert( p <= (buf+length) ); 1042 } 1043 else if ( *p == 0xd ) { 1044 // Carriage return. Append what we have so far, then 1045 // handle moving forward in the buffer. 1046 if ( (p-lastPos) > 0 ) { 1047 data.append( lastPos, p-lastPos ); // do not add the CR 1048 } 1049 data += (char)0xa; // a proper newline 1050 1051 if ( *(p+1) == 0xa ) { 1052 // Carriage return - new line sequence 1053 p += 2; 1054 lastPos = p; 1055 assert( p <= (buf+length) ); 1056 } 1057 else { 1058 // it was followed by something else...that is presumably characters again. 1059 ++p; 1060 lastPos = p; 1061 assert( p <= (buf+length) ); 1062 } 1063 } 1064 else { 1065 ++p; 1066 } 1067 } 1068 // Handle any left over characters. 1069 if ( p-lastPos ) { 1070 data.append( lastPos, p-lastPos ); 1071 } 1072 delete [] buf; 1073 buf = 0; 1074 1075 Parse( data.c_str(), 0, encoding ); 1076 1077 if ( Error() ) 1078 return false; 1079 else 1080 return true; 1081 } 1082 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 1083 return false; 1084 } 1085 SaveFile(const char * filename) const1086 bool TiXmlDocument::SaveFile( const char * filename ) const 1087 { 1088 // The old c stuff lives on... 1089 FILE* fp = fopen( filename, "w" ); 1090 if ( fp ) 1091 { 1092 if ( useMicrosoftBOM ) 1093 { 1094 const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 1095 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 1096 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 1097 1098 fputc( TIXML_UTF_LEAD_0, fp ); 1099 fputc( TIXML_UTF_LEAD_1, fp ); 1100 fputc( TIXML_UTF_LEAD_2, fp ); 1101 } 1102 Print( fp, 0 ); 1103 fclose( fp ); 1104 return true; 1105 } 1106 return false; 1107 } 1108 1109 CopyTo(TiXmlDocument * target) const1110 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const 1111 { 1112 TiXmlNode::CopyTo( target ); 1113 1114 target->error = error; 1115 target->errorDesc = errorDesc.c_str (); 1116 1117 TiXmlNode* node = 0; 1118 for ( node = firstChild; node; node = node->NextSibling() ) 1119 { 1120 target->LinkEndChild( node->Clone() ); 1121 } 1122 } 1123 1124 Clone() const1125 TiXmlNode* TiXmlDocument::Clone() const 1126 { 1127 TiXmlDocument* clone = new TiXmlDocument(); 1128 if ( !clone ) 1129 return 0; 1130 1131 CopyTo( clone ); 1132 return clone; 1133 } 1134 1135 Print(FILE * cfile,int depth) const1136 void TiXmlDocument::Print( FILE* cfile, int depth ) const 1137 { 1138 const TiXmlNode* node; 1139 for ( node=FirstChild(); node; node=node->NextSibling() ) 1140 { 1141 node->Print( cfile, depth ); 1142 fprintf( cfile, "\n" ); 1143 } 1144 } 1145 StreamOut(TIXML_OSTREAM * out) const1146 void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const 1147 { 1148 const TiXmlNode* node; 1149 for ( node=FirstChild(); node; node=node->NextSibling() ) 1150 { 1151 node->StreamOut( out ); 1152 1153 // Special rule for streams: stop after the root element. 1154 // The stream in code will only read one element, so don't 1155 // write more than one. 1156 if ( node->ToElement() ) 1157 break; 1158 } 1159 } 1160 1161 Next() const1162 const TiXmlAttribute* TiXmlAttribute::Next() const 1163 { 1164 // We are using knowledge of the sentinel. The sentinel 1165 // have a value or name. 1166 if ( next->value.empty() && next->name.empty() ) 1167 return 0; 1168 return next; 1169 } 1170 Next()1171 TiXmlAttribute* TiXmlAttribute::Next() 1172 { 1173 // We are using knowledge of the sentinel. The sentinel 1174 // have a value or name. 1175 if ( next->value.empty() && next->name.empty() ) 1176 return 0; 1177 return next; 1178 } 1179 Previous() const1180 const TiXmlAttribute* TiXmlAttribute::Previous() const 1181 { 1182 // We are using knowledge of the sentinel. The sentinel 1183 // have a value or name. 1184 if ( prev->value.empty() && prev->name.empty() ) 1185 return 0; 1186 return prev; 1187 } 1188 Previous()1189 TiXmlAttribute* TiXmlAttribute::Previous() 1190 { 1191 // We are using knowledge of the sentinel. The sentinel 1192 // have a value or name. 1193 if ( prev->value.empty() && prev->name.empty() ) 1194 return 0; 1195 return prev; 1196 } 1197 Print(FILE * cfile,int) const1198 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const 1199 { 1200 TIXML_STRING n, v; 1201 1202 PutString( name, &n ); 1203 PutString( value, &v ); 1204 1205 if (value.find ('\"') == TIXML_STRING::npos) 1206 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); 1207 else 1208 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); 1209 } 1210 1211 StreamOut(TIXML_OSTREAM * stream) const1212 void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const 1213 { 1214 if (value.find( '\"' ) != TIXML_STRING::npos) 1215 { 1216 PutString( name, stream ); 1217 (*stream) << "=" << "'"; 1218 PutString( value, stream ); 1219 (*stream) << "'"; 1220 } 1221 else 1222 { 1223 PutString( name, stream ); 1224 (*stream) << "=" << "\""; 1225 PutString( value, stream ); 1226 (*stream) << "\""; 1227 } 1228 } 1229 QueryIntValue(int * ival) const1230 int TiXmlAttribute::QueryIntValue( int* ival ) const 1231 { 1232 if ( sscanf( value.c_str(), "%d", ival ) == 1 ) 1233 return TIXML_SUCCESS; 1234 return TIXML_WRONG_TYPE; 1235 } 1236 QueryDoubleValue(double * dval) const1237 int TiXmlAttribute::QueryDoubleValue( double* dval ) const 1238 { 1239 if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) 1240 return TIXML_SUCCESS; 1241 return TIXML_WRONG_TYPE; 1242 } 1243 SetIntValue(int _value)1244 void TiXmlAttribute::SetIntValue( int _value ) 1245 { 1246 char buf [64]; 1247 #if defined(TIXML_SNPRINTF) 1248 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); 1249 #else 1250 sprintf (buf, "%d", _value); 1251 #endif 1252 SetValue (buf); 1253 } 1254 SetDoubleValue(double _value)1255 void TiXmlAttribute::SetDoubleValue( double _value ) 1256 { 1257 char buf [256]; 1258 #if defined(TIXML_SNPRINTF) 1259 TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); 1260 #else 1261 sprintf (buf, "%lf", _value); 1262 #endif 1263 SetValue (buf); 1264 } 1265 IntValue() const1266 int TiXmlAttribute::IntValue() const 1267 { 1268 return atoi (value.c_str ()); 1269 } 1270 DoubleValue() const1271 double TiXmlAttribute::DoubleValue() const 1272 { 1273 return atof (value.c_str ()); 1274 } 1275 1276 TiXmlComment(const TiXmlComment & copy)1277 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) 1278 { 1279 copy.CopyTo( this ); 1280 } 1281 1282 operator =(const TiXmlComment & base)1283 void TiXmlComment::operator=( const TiXmlComment& base ) 1284 { 1285 Clear(); 1286 base.CopyTo( this ); 1287 } 1288 1289 Print(FILE * cfile,int depth) const1290 void TiXmlComment::Print( FILE* cfile, int depth ) const 1291 { 1292 for ( int i=0; i<depth; i++ ) 1293 { 1294 fputs( " ", cfile ); 1295 } 1296 fprintf( cfile, "<!--%s-->", value.c_str() ); 1297 } 1298 StreamOut(TIXML_OSTREAM * stream) const1299 void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const 1300 { 1301 (*stream) << "<!--"; 1302 //PutString( value, stream ); 1303 (*stream) << value; 1304 (*stream) << "-->"; 1305 } 1306 1307 CopyTo(TiXmlComment * target) const1308 void TiXmlComment::CopyTo( TiXmlComment* target ) const 1309 { 1310 TiXmlNode::CopyTo( target ); 1311 } 1312 1313 Clone() const1314 TiXmlNode* TiXmlComment::Clone() const 1315 { 1316 TiXmlComment* clone = new TiXmlComment(); 1317 1318 if ( !clone ) 1319 return 0; 1320 1321 CopyTo( clone ); 1322 return clone; 1323 } 1324 1325 Print(FILE * cfile,int depth) const1326 void TiXmlText::Print( FILE* cfile, int depth ) const 1327 { 1328 if ( cdata ) 1329 { 1330 int i; 1331 fprintf( cfile, "\n" ); 1332 for ( i=0; i<depth; i++ ) { 1333 fprintf( cfile, " " ); 1334 } 1335 fprintf( cfile, "<![CDATA[\n" ); 1336 1337 fprintf( cfile, "%s", value.c_str() ); // unformatted output 1338 1339 fprintf( cfile, "\n" ); 1340 for ( i=0; i<depth; i++ ) { 1341 fprintf( cfile, " " ); 1342 } 1343 fprintf( cfile, "]]>\n" ); 1344 } 1345 else 1346 { 1347 TIXML_STRING buffer; 1348 PutString( value, &buffer ); 1349 fprintf( cfile, "%s", buffer.c_str() ); 1350 } 1351 } 1352 1353 StreamOut(TIXML_OSTREAM * stream) const1354 void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const 1355 { 1356 if ( cdata ) 1357 { 1358 (*stream) << "<![CDATA[" << value << "]]>"; 1359 } 1360 else 1361 { 1362 PutString( value, stream ); 1363 } 1364 } 1365 1366 CopyTo(TiXmlText * target) const1367 void TiXmlText::CopyTo( TiXmlText* target ) const 1368 { 1369 TiXmlNode::CopyTo( target ); 1370 target->cdata = cdata; 1371 } 1372 1373 Clone() const1374 TiXmlNode* TiXmlText::Clone() const 1375 { 1376 TiXmlText* clone = 0; 1377 clone = new TiXmlText( "" ); 1378 1379 if ( !clone ) 1380 return 0; 1381 1382 CopyTo( clone ); 1383 return clone; 1384 } 1385 1386 TiXmlDeclaration(const char * _version,const char * _encoding,const char * _standalone)1387 TiXmlDeclaration::TiXmlDeclaration( const char * _version, 1388 const char * _encoding, 1389 const char * _standalone ) 1390 : TiXmlNode( TiXmlNode::DECLARATION ) 1391 { 1392 version = _version; 1393 encoding = _encoding; 1394 standalone = _standalone; 1395 } 1396 1397 1398 #ifdef TIXML_USE_STL TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)1399 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, 1400 const std::string& _encoding, 1401 const std::string& _standalone ) 1402 : TiXmlNode( TiXmlNode::DECLARATION ) 1403 { 1404 version = _version; 1405 encoding = _encoding; 1406 standalone = _standalone; 1407 } 1408 #endif 1409 1410 TiXmlDeclaration(const TiXmlDeclaration & copy)1411 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) 1412 : TiXmlNode( TiXmlNode::DECLARATION ) 1413 { 1414 copy.CopyTo( this ); 1415 } 1416 1417 operator =(const TiXmlDeclaration & copy)1418 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) 1419 { 1420 Clear(); 1421 copy.CopyTo( this ); 1422 } 1423 1424 Print(FILE * cfile,int) const1425 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const 1426 { 1427 fprintf (cfile, "<?xml "); 1428 1429 if ( !version.empty() ) 1430 fprintf (cfile, "version=\"%s\" ", version.c_str ()); 1431 if ( !encoding.empty() ) 1432 fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); 1433 if ( !standalone.empty() ) 1434 fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); 1435 fprintf (cfile, "?>"); 1436 } 1437 StreamOut(TIXML_OSTREAM * stream) const1438 void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const 1439 { 1440 (*stream) << "<?xml "; 1441 1442 if ( !version.empty() ) 1443 { 1444 (*stream) << "version=\""; 1445 PutString( version, stream ); 1446 (*stream) << "\" "; 1447 } 1448 if ( !encoding.empty() ) 1449 { 1450 (*stream) << "encoding=\""; 1451 PutString( encoding, stream ); 1452 (*stream ) << "\" "; 1453 } 1454 if ( !standalone.empty() ) 1455 { 1456 (*stream) << "standalone=\""; 1457 PutString( standalone, stream ); 1458 (*stream) << "\" "; 1459 } 1460 (*stream) << "?>"; 1461 } 1462 1463 CopyTo(TiXmlDeclaration * target) const1464 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const 1465 { 1466 TiXmlNode::CopyTo( target ); 1467 1468 target->version = version; 1469 target->encoding = encoding; 1470 target->standalone = standalone; 1471 } 1472 1473 Clone() const1474 TiXmlNode* TiXmlDeclaration::Clone() const 1475 { 1476 TiXmlDeclaration* clone = new TiXmlDeclaration(); 1477 1478 if ( !clone ) 1479 return 0; 1480 1481 CopyTo( clone ); 1482 return clone; 1483 } 1484 1485 Print(FILE * cfile,int depth) const1486 void TiXmlUnknown::Print( FILE* cfile, int depth ) const 1487 { 1488 for ( int i=0; i<depth; i++ ) 1489 fprintf( cfile, " " ); 1490 fprintf( cfile, "<%s>", value.c_str() ); 1491 } 1492 1493 StreamOut(TIXML_OSTREAM * stream) const1494 void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const 1495 { 1496 (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown. 1497 } 1498 1499 CopyTo(TiXmlUnknown * target) const1500 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const 1501 { 1502 TiXmlNode::CopyTo( target ); 1503 } 1504 1505 Clone() const1506 TiXmlNode* TiXmlUnknown::Clone() const 1507 { 1508 TiXmlUnknown* clone = new TiXmlUnknown(); 1509 1510 if ( !clone ) 1511 return 0; 1512 1513 CopyTo( clone ); 1514 return clone; 1515 } 1516 1517 TiXmlAttributeSet()1518 TiXmlAttributeSet::TiXmlAttributeSet() 1519 { 1520 sentinel.next = &sentinel; 1521 sentinel.prev = &sentinel; 1522 } 1523 1524 ~TiXmlAttributeSet()1525 TiXmlAttributeSet::~TiXmlAttributeSet() 1526 { 1527 assert( sentinel.next == &sentinel ); 1528 assert( sentinel.prev == &sentinel ); 1529 } 1530 1531 Add(TiXmlAttribute * addMe)1532 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) 1533 { 1534 assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. 1535 1536 addMe->next = &sentinel; 1537 addMe->prev = sentinel.prev; 1538 1539 sentinel.prev->next = addMe; 1540 sentinel.prev = addMe; 1541 } 1542 Remove(TiXmlAttribute * removeMe)1543 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) 1544 { 1545 TiXmlAttribute* node; 1546 1547 for( node = sentinel.next; node != &sentinel; node = node->next ) 1548 { 1549 if ( node == removeMe ) 1550 { 1551 node->prev->next = node->next; 1552 node->next->prev = node->prev; 1553 node->next = 0; 1554 node->prev = 0; 1555 return; 1556 } 1557 } 1558 assert( 0 ); // we tried to remove a non-linked attribute. 1559 } 1560 Find(const char * name) const1561 const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const 1562 { 1563 const TiXmlAttribute* node; 1564 1565 for( node = sentinel.next; node != &sentinel; node = node->next ) 1566 { 1567 if ( node->name == name ) 1568 return node; 1569 } 1570 return 0; 1571 } 1572 Find(const char * name)1573 TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) 1574 { 1575 TiXmlAttribute* node; 1576 1577 for( node = sentinel.next; node != &sentinel; node = node->next ) 1578 { 1579 if ( node->name == name ) 1580 return node; 1581 } 1582 return 0; 1583 } 1584 1585 #ifdef TIXML_USE_STL operator >>(TIXML_ISTREAM & in,TiXmlNode & base)1586 TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base) 1587 { 1588 TIXML_STRING tag; 1589 tag.reserve( 8 * 1000 ); 1590 base.StreamIn( &in, &tag ); 1591 1592 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); 1593 return in; 1594 } 1595 #endif 1596 1597 operator <<(TIXML_OSTREAM & out,const TiXmlNode & base)1598 TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base) 1599 { 1600 base.StreamOut (& out); 1601 return out; 1602 } 1603 1604 1605 #ifdef TIXML_USE_STL operator <<(std::string & out,const TiXmlNode & base)1606 std::string & operator<< (std::string& out, const TiXmlNode& base ) 1607 { 1608 std::ostringstream os_stream( std::ostringstream::out ); 1609 base.StreamOut( &os_stream ); 1610 1611 out.append( os_stream.str() ); 1612 return out; 1613 } 1614 #endif 1615 1616 FirstChild() const1617 TiXmlHandle TiXmlHandle::FirstChild() const 1618 { 1619 if ( node ) 1620 { 1621 TiXmlNode* child = node->FirstChild(); 1622 if ( child ) 1623 return TiXmlHandle( child ); 1624 } 1625 return TiXmlHandle( 0 ); 1626 } 1627 1628 FirstChild(const char * value) const1629 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const 1630 { 1631 if ( node ) 1632 { 1633 TiXmlNode* child = node->FirstChild( value ); 1634 if ( child ) 1635 return TiXmlHandle( child ); 1636 } 1637 return TiXmlHandle( 0 ); 1638 } 1639 1640 FirstChildElement() const1641 TiXmlHandle TiXmlHandle::FirstChildElement() const 1642 { 1643 if ( node ) 1644 { 1645 TiXmlElement* child = node->FirstChildElement(); 1646 if ( child ) 1647 return TiXmlHandle( child ); 1648 } 1649 return TiXmlHandle( 0 ); 1650 } 1651 1652 FirstChildElement(const char * value) const1653 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const 1654 { 1655 if ( node ) 1656 { 1657 TiXmlElement* child = node->FirstChildElement( value ); 1658 if ( child ) 1659 return TiXmlHandle( child ); 1660 } 1661 return TiXmlHandle( 0 ); 1662 } 1663 1664 Child(int count) const1665 TiXmlHandle TiXmlHandle::Child( int count ) const 1666 { 1667 if ( node ) 1668 { 1669 int i; 1670 TiXmlNode* child = node->FirstChild(); 1671 for ( i=0; 1672 child && i<count; 1673 child = child->NextSibling(), ++i ) 1674 { 1675 // nothing 1676 } 1677 if ( child ) 1678 return TiXmlHandle( child ); 1679 } 1680 return TiXmlHandle( 0 ); 1681 } 1682 1683 Child(const char * value,int count) const1684 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const 1685 { 1686 if ( node ) 1687 { 1688 int i; 1689 TiXmlNode* child = node->FirstChild( value ); 1690 for ( i=0; 1691 child && i<count; 1692 child = child->NextSibling( value ), ++i ) 1693 { 1694 // nothing 1695 } 1696 if ( child ) 1697 return TiXmlHandle( child ); 1698 } 1699 return TiXmlHandle( 0 ); 1700 } 1701 1702 ChildElement(int count) const1703 TiXmlHandle TiXmlHandle::ChildElement( int count ) const 1704 { 1705 if ( node ) 1706 { 1707 int i; 1708 TiXmlElement* child = node->FirstChildElement(); 1709 for ( i=0; 1710 child && i<count; 1711 child = child->NextSiblingElement(), ++i ) 1712 { 1713 // nothing 1714 } 1715 if ( child ) 1716 return TiXmlHandle( child ); 1717 } 1718 return TiXmlHandle( 0 ); 1719 } 1720 1721 ChildElement(const char * value,int count) const1722 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const 1723 { 1724 if ( node ) 1725 { 1726 int i; 1727 TiXmlElement* child = node->FirstChildElement( value ); 1728 for ( i=0; 1729 child && i<count; 1730 child = child->NextSiblingElement( value ), ++i ) 1731 { 1732 // nothing 1733 } 1734 if ( child ) 1735 return TiXmlHandle( child ); 1736 } 1737 return TiXmlHandle( 0 ); 1738 } 1739