1 /* 2 http://code.google.com/p/ticpp/ 3 Copyright (c) 2006 Ryan Pusztai, Ryan Mulder 4 5 Permission is hereby granted, free of charge, to any person obtaining a copy of 6 this software and associated documentation files (the "Software"), to deal in 7 the Software without restriction, including without limitation the rights to 8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 the Software, and to permit persons to whom the Software is furnished to do so, 10 subject to the following conditions: 11 12 The above copyright notice and this permission notice shall be included in all 13 copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 /** 24 @copydoc ticpp 25 @file 26 @author Ryan Pusztai 27 @author Ryan Mulder 28 @date 04/11/2006 29 30 @version 0.04a by edam@waxworlds.org: based Exception based on std::exception; added stream 31 << and >> support; added Document::Parse(); bug fix; improved THROW() macro. 32 @version 0.04 Added NodeImp class. Also made all the classes inherit from NodeImp. 33 @version 0.03 Added Declaration class 34 @version 0.02 Added Element class 35 @version 0.01 Added Exception class, Document class 36 37 @todo add UNKNOWN support. See ticpp::NodeFactory. 38 @todo add TYPECOUNT support. See ticpp::NodeFactory. 39 @todo Add a quick reference 40 */ 41 42 /* 43 * THIS FILE WAS ALTERED BY Matt Janisz, 12. October 2012. 44 * 45 * - added ticppapi.h include and TICPP_API dll-interface to support building DLL using VS200X 46 */ 47 48 #ifndef TIXML_USE_TICPP 49 #define TIXML_USE_TICPP 50 #endif 51 52 #ifndef TICPP_INCLUDED 53 #define TICPP_INCLUDED 54 55 #include "ticppapi.h" 56 #include "tinyxml.h" 57 #include <sstream> 58 #include <vector> 59 #include <memory> 60 #include <exception> 61 #include <typeinfo> 62 63 /** 64 @subpage ticpp is a TinyXML wrapper that uses a lot more C++ ideals. 65 It throws exceptions, uses templates, is in its own name space, and 66 <b>requires</b> STL (Standard Template Library). This is done to ease the use 67 of getting values in and out of the xml. 68 69 If you don't perfer to use some of the concepts just don't use it. 70 It is just a wrapper that extends TinyXML. It doesn't actually change 71 any of TinyXML. 72 */ 73 namespace ticpp 74 { 75 /** 76 This is a ticpp exception class 77 */ 78 class TICPP_API Exception : public std::exception 79 { 80 public: 81 /** 82 Construct an exception with a message 83 */ 84 Exception( const std::string& details ); 85 ~Exception() throw(); 86 87 /// Override std::exception::what() to return m_details 88 const char* what() const throw(); 89 90 std::string m_details; /**< Exception Details */ 91 }; 92 93 /** 94 This allows you to stream your exceptions in. 95 It will take care of the conversion and throwing the exception. 96 */ 97 #define TICPPTHROW( message ) \ 98 { \ 99 std::ostringstream full_message; \ 100 std::string file( __FILE__ ); \ 101 file = file.substr( file.find_last_of( "\\/" ) + 1 ); \ 102 full_message << message << " <" << file << "@" << __LINE__ << ">"; \ 103 full_message << BuildDetailedErrorString(); \ 104 throw Exception( full_message.str() ); \ 105 } 106 107 // Forward Declarations for Visitor, and others. 108 class TICPP_API Document; 109 class TICPP_API Element; 110 class TICPP_API Declaration; 111 class TICPP_API StylesheetReference; 112 class TICPP_API Text; 113 class TICPP_API Comment; 114 class TICPP_API Attribute; 115 116 /** Wrapper around TiXmlVisitor */ 117 class TICPP_API Visitor : public TiXmlVisitor 118 { 119 public: 120 // Overload the TiXmlVisitor functions, wrap objects, call ticpp::Visitor functions 121 /// @internal 122 virtual bool VisitEnter( const TiXmlDocument& doc ); 123 /// @internal 124 virtual bool VisitExit( const TiXmlDocument& doc ); 125 /// @internal 126 virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); 127 /// @internal 128 virtual bool VisitExit( const TiXmlElement& element ); 129 /// @internal 130 virtual bool Visit( const TiXmlDeclaration& declaration ); 131 /// @internal 132 virtual bool Visit( const TiXmlStylesheetReference& stylesheet ); 133 /// @internal 134 virtual bool Visit( const TiXmlText& text ); 135 /// @internal 136 virtual bool Visit( const TiXmlComment& comment ); 137 138 public: 139 /// Visit a document. VisitEnter(const Document &)140 virtual bool VisitEnter( const Document& /*doc*/ ) { return true; } 141 /// Visit a document. VisitExit(const Document &)142 virtual bool VisitExit( const Document& /*doc*/ ) { return true; } 143 144 /// Visit an element. VisitEnter(const Element &,const Attribute *)145 virtual bool VisitEnter( const Element& /*element*/, const Attribute* /*firstAttribute*/ ) { return true; } 146 /// Visit an element. VisitExit(const Element &)147 virtual bool VisitExit( const Element& /*element*/ ) { return true; } 148 149 /// Visit a declaration Visit(const Declaration &)150 virtual bool Visit( const Declaration& /*declaration*/ ) { return true; } 151 /// Visit a stylesheet reference Visit(const StylesheetReference &)152 virtual bool Visit( const StylesheetReference& /*stylesheet*/ ) { return true; } 153 /// Visit a text node Visit(const Text &)154 virtual bool Visit( const Text& /*text*/ ) { return true; } 155 /// Visit a comment node Visit(const Comment &)156 virtual bool Visit( const Comment& /*comment*/ ) { return true; } 157 }; 158 159 /** Wrapper around TiXmlBase */ 160 class TICPP_API Base 161 { 162 public: 163 164 /** 165 Converts any class with a proper overload of the << opertor to a std::string 166 @param value The value to be converted 167 @throws Exception When value cannot be converted to a std::string 168 */ 169 template < class T > ToString(const T & value)170 std::string ToString( const T& value ) const 171 { 172 std::stringstream convert; 173 convert << value; 174 if ( convert.fail() ) 175 { 176 TICPPTHROW( "Could not convert value to text" ); 177 } 178 return convert.str(); 179 } 180 ToString(const std::string & value)181 std::string ToString( const std::string& value ) const 182 { 183 return value; 184 } 185 186 /** 187 Converts a std::string to any class with a proper overload of the >> opertor 188 @param temp The string to be converted 189 @param out [OUT] The container for the returned value 190 @throws Exception When temp cannot be converted to the target type 191 */ 192 template < class T > FromString(const std::string & temp,T * out)193 void FromString( const std::string& temp, T* out ) const 194 { 195 std::istringstream val( temp ); 196 val >> *out; 197 198 if ( val.fail() ) 199 { 200 TICPPTHROW( "Could not convert \"" << temp << "\" to target type" ); 201 } 202 } 203 204 /** 205 Specialization for std::string 206 */ FromString(const std::string & temp,std::string * out)207 void FromString( const std::string& temp, std::string* out ) const 208 { 209 *out = temp; 210 } 211 212 /** 213 Return the position, in the original source file, of this node or attribute. 214 Wrapper around TiXmlBase::Row() 215 */ Row()216 int Row() const 217 { 218 return GetBasePointer()->Row(); 219 } 220 221 /** 222 Return the position, in the original source file, of this node or attribute. 223 Wrapper around TiXmlBase::Row() 224 */ Column()225 int Column() const 226 { 227 return GetBasePointer()->Column(); 228 } 229 230 /** 231 Compare internal TiXml pointers to determine is both are wrappers around the same node 232 */ 233 bool operator == ( const Base& rhs ) const 234 { 235 return ( GetBasePointer() == rhs.GetBasePointer() ); 236 } 237 238 /** 239 Compare internal TiXml pointers to determine is both are wrappers around the same node 240 */ 241 bool operator != ( const Base& rhs ) const 242 { 243 return ( GetBasePointer() != rhs.GetBasePointer() ); 244 } 245 246 /** 247 Builds detailed error string using TiXmlDocument::Error() and others 248 */ BuildDetailedErrorString()249 std::string BuildDetailedErrorString() const 250 { 251 std::ostringstream full_message; 252 #ifndef TICPP_NO_RTTI 253 TiXmlNode* node = dynamic_cast< TiXmlNode* >( GetBasePointer() ); 254 if ( node != 0 ) 255 { 256 TiXmlDocument* doc = node->GetDocument(); 257 if ( doc != 0 ) 258 { 259 if ( doc->Error() ) 260 { 261 full_message << "\nDescription: " << doc->ErrorDesc() 262 << "\nFile: " << (strlen( doc->Value() ) > 0 ? doc->Value() : "<unnamed-file>") 263 << "\nLine: " << doc->ErrorRow() 264 << "\nColumn: " << doc->ErrorCol(); 265 } 266 } 267 } 268 #endif 269 return full_message.str(); 270 } 271 272 /** 273 Destructor 274 */ ~Base()275 virtual ~Base() 276 { 277 } 278 279 protected: 280 mutable TiCppRCImp* m_impRC; /**< Holds status of internal TiXmlPointer - use this to determine if object has been deleted already */ 281 282 /** 283 @internal 284 Updates the pointer to the reference counter to point at the counter in the new node. 285 286 @param node TiXmlBase containing the new reference counter 287 */ SetImpRC(TiXmlBase * node)288 void SetImpRC( TiXmlBase* node ) 289 { 290 m_impRC = node->m_tiRC; 291 } 292 ValidatePointer()293 void ValidatePointer() const 294 { 295 if ( m_impRC->IsNull() ) 296 { 297 TICPPTHROW( "Internal TiXml Pointer is NULL" ); 298 } 299 } 300 301 /** 302 @internal 303 Get internal TiXmlBase* 304 */ 305 virtual TiXmlBase* GetBasePointer() const = 0; 306 }; 307 308 /** 309 Wrapper around TiXmlAttribute 310 */ 311 class TICPP_API Attribute : public Base 312 { 313 private: 314 TiXmlAttribute* m_tiXmlPointer; GetBasePointer()315 TiXmlBase* GetBasePointer() const 316 { 317 ValidatePointer(); 318 return m_tiXmlPointer; 319 } 320 321 public: 322 /** 323 Construct an empty attribute. 324 */ 325 Attribute(); 326 327 /** 328 Construct an attribute with @a name and @a value 329 330 @param name The name of the attribute 331 @param value The value of the attribute 332 */ 333 Attribute( const std::string& name, const std::string& value ); 334 335 /** 336 @internal 337 Construct an attribute with the internal pointer 338 339 @param attribute The internal pointer 340 */ 341 Attribute( TiXmlAttribute* attribute ); 342 343 /** 344 Get the value of this attribute 345 Uses Base::FromString to convert TiXmlAttribute::ValueStr from a std::string, 346 and puts it in the passed pointer. 347 348 @param value [OUT] A pointer to fill with the value 349 */ 350 template < class T > GetValue(T * value)351 void GetValue( T* value ) const 352 { 353 ValidatePointer(); 354 FromString( m_tiXmlPointer->ValueStr(), value ); 355 } 356 357 /** 358 Get the value of this attribute. 359 Simple wrapper for TiXmlAttribute::ValueStr. 360 361 @see GetValue 362 */ 363 std::string Value() const; 364 365 /** 366 Set the value of this node. 367 Uses Base::ToString to convert value to a std::string, then calls TiXmlAttribute::SetValue. 368 369 @param value The value to set 370 */ 371 template < class T > SetValue(const T & value)372 void SetValue( const T& value ) 373 { 374 ValidatePointer(); 375 m_tiXmlPointer->SetValue( ToString( value ) ); 376 } 377 378 /** 379 Get the value of this attribute 380 Uses Base::FromString to convert TiXmlAttribute::Name from a std::string, 381 and puts it in the passed pointer. 382 383 @param name [OUT] A pointer to fill with the name 384 */ 385 template < class T > GetName(T * name)386 void GetName( T* name ) const 387 { 388 ValidatePointer(); 389 FromString( m_tiXmlPointer->Name(), name ); 390 } 391 392 /** 393 Get the value of this attribute. 394 Simple wrapper for TiXmlAttribute::Name. 395 396 @see GetName 397 */ 398 std::string Name() const; 399 400 /** 401 Set the value of this attribute. 402 Uses Base::ToString to convert @a name to a std::string, then calls TiXmlAttribute::SetName. 403 404 @param name The name to set 405 */ 406 template < class T > SetName(const T & name)407 void SetName( const T& name ) 408 { 409 ValidatePointer(); 410 m_tiXmlPointer->SetName( ToString( name ) ); 411 } 412 413 /** 414 @internal 415 Updates the reference count for the old and new pointers. 416 */ 417 void operator=( const Attribute& copy ); 418 419 /** 420 @internal 421 Updates the reference count for the old and new pointers. 422 */ 423 Attribute( const Attribute& copy ); 424 425 /* 426 Decrements reference count. 427 */ 428 ~Attribute(); 429 430 /** 431 Get the next sibling attribute in the DOM. 432 */ 433 Attribute* Next( bool throwIfNoAttribute = true ) const; 434 435 /** 436 Get the previous sibling attribute in the DOM. 437 */ 438 Attribute* Previous( bool throwIfNoAttribute = true ) const; 439 440 /** 441 @internal 442 Just for Iterator<> 443 444 @param next [OUT] The pointer to the next valid attribute 445 @return true if there is a next attribute, false if not 446 */ 447 void IterateNext( const std::string&, Attribute** next ) const; 448 449 /** 450 @internal 451 Just for Iterator<> 452 453 @param previous [OUT] The pointer to the previous valid attribute 454 @return true if there is a previous attribute, false if not 455 */ 456 void IteratePrevious( const std::string&, Attribute** previous ) const; 457 458 /** 459 All TinyXml classes can print themselves to a filestream. 460 */ 461 virtual void Print( FILE* file, int depth ) const; 462 463 private: 464 465 /** 466 @internal 467 Sets the internal pointer. 468 Saves a copy of the pointer to the RC object. 469 470 @param newPointer TiXmlAttribute* to set. 471 */ 472 void SetTiXmlPointer( TiXmlAttribute* newPointer ); 473 }; 474 475 /** 476 Wrapper around TiXmlNode 477 */ 478 class TICPP_API Node : public Base 479 { 480 public: 481 482 /** 483 Get the value of this node 484 Uses Base::FromString to convert TiXmlNode::ValueStr from a std::string, 485 and puts it in the passed pointer. 486 487 @param value [OUT] A pointer to fill with the value 488 */ 489 template < class T > GetValue(T * value)490 void GetValue( T* value) const 491 { 492 FromString( GetTiXmlPointer()->ValueStr(), value ); 493 } 494 495 /** 496 Get the value of this node. 497 Simple wrapper for TiXmlNode::ValueStr. 498 499 @see GetValue 500 */ 501 std::string Value() const; 502 503 /** 504 Set the value of this node. 505 Uses Base::ToString to convert value to a std::string, then calls TiXmlNode::SetValue. 506 507 @param value The value to set 508 */ 509 template < class T > SetValue(const T & value)510 void SetValue( const T& value ) 511 { 512 GetTiXmlPointer()->SetValue( ToString( value ) ); 513 } 514 515 /** 516 Clear all Nodes below this. 517 Simple wrapper for TiXmlNode::Clear. 518 */ 519 void Clear(); 520 521 /** 522 The Parent of this Node. 523 Simple wrapper for TiXmlNode::Parent. 524 525 @param throwIfNoParent [DEF] If true, throws when Parent = NULL. 526 @return The parent of this node, NULL if there is no Parent. 527 @throws Exception When throwIfNoParent is true, and TiXmlNode::Parent returns Null. 528 */ 529 Node* Parent( bool throwIfNoParent = true ) const; 530 531 /** 532 The first child of this node. 533 534 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 535 @return Pointer to child, Null if no children and 'throwIfNoChildren' is false. 536 @throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChild returns Null. 537 538 @see TiXmlNode::FirstChild 539 */ 540 Node* FirstChild( bool throwIfNoChildren = true ) const; 541 542 /** 543 @internal 544 The first child of this node with the matching @a value. 545 546 @overload 547 @param value Value to match. 548 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 549 550 @see FirstChild( bool throwIfNoChildren = true ) 551 */ 552 Node* FirstChild( const char* value, bool throwIfNoChildren = true ) const; 553 554 /** 555 The first child of this node with the matching @a value. 556 557 @overload 558 @param value Value to match. 559 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 560 561 @see FirstChild( const char* value, bool throwIfNoChildren = true ) 562 */ 563 Node* FirstChild( const std::string& value, bool throwIfNoChildren = true ) const; 564 565 /** 566 The last child of this node. 567 568 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 569 @return Pointer to child, Null if no children and 'throwIfNoChildren' is false. 570 @throws Exception When throwIfNoChildren is true, and TiXmlNode::LastChild returns Null. 571 572 @see TiXmlNode::LastChild 573 */ 574 Node* LastChild( bool throwIfNoChildren = true ) const; 575 576 /** 577 @internal 578 The last child of this node with the matching @a value. 579 580 @overload 581 @param value Value to match. 582 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 583 584 @see LastChild( bool throwIfNoChildren = true ) 585 */ 586 Node* LastChild( const char* value, bool throwIfNoChildren = true ) const; 587 588 /** 589 The last child of this node with the matching @a value. 590 591 @overload 592 @param value Value to match. 593 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no children. 594 595 @see LastChild( const char* value, bool throwIfNoChildren = true ) 596 */ 597 Node* LastChild( const std::string& value, bool throwIfNoChildren = true ) const; 598 599 /** 600 An alternate way to walk the children of a node. 601 Simple wrapper for TiXmlNode::IterateChildren. 602 603 @param previous The previous Node* that was returned from IterateChildren. 604 @return NULL When there are no more children. 605 */ 606 Node* IterateChildren( Node* previous ) const; 607 608 /** 609 This flavor of IterateChildren searches for children with a particular @a value. 610 Simple wrapper for TiXmlNode::IterateChildren. 611 612 @param value The value you want to search for. 613 @param previous The previous Node* that was returned from IterateChildren. 614 @return NULL When there are no more children. 615 */ 616 Node* IterateChildren( const std::string& value, Node* previous ) const; 617 618 /** 619 Adds a child past the LastChild. 620 Throws if you try to insert a document. 621 622 @note This takes a copy of @a addThis so it is not as efficiant as LinkEndChild. 623 @param addThis Node to insert. 624 @throws Exception When TiXmlNode::InsertEndChild returns Null 625 626 @see LinkEndChild 627 @see TiXmlNode::InsertEndChild 628 */ 629 Node* InsertEndChild( const Node& addThis ); 630 631 /** 632 Adds a child past the LastChild. 633 Throws if you try to link a document. 634 635 @param childNode Node to link. 636 @throws Exception When TiXmlNode::LinkEndChild returns Null. 637 638 @see InsertEndChild 639 @see TiXmlNode::LinkEndChild 640 */ 641 Node* LinkEndChild( Node* childNode ); 642 643 /** 644 Adds a child before the specified child. 645 Throws if you try to insert a document. 646 647 @param beforeThis Node that will have @a addThis linked before. 648 @param addThis Node to insert before. 649 @throws Exception When TiXmlNode::InsertBeforeChild returns Null. 650 651 @see InsertAfterChild 652 @see TiXmlNode::InsertBeforeChild 653 */ 654 Node* InsertBeforeChild( Node* beforeThis, const Node& addThis ); 655 656 /** 657 Adds a child after the specified child. 658 Throws if you try to insert a document. 659 660 @param afterThis Node that will have @a addThis linked after. 661 @param addThis Node to insert after. 662 @throws Exception When TiXmlNode::InsertAfterChild returns Null. 663 664 @see InsertBeforeChild 665 @see TiXmlNode::InsertAfterChild 666 */ 667 Node* InsertAfterChild( Node* afterThis, const Node& addThis ); 668 669 /** 670 Replace a child of this node. 671 Throws if you try to replace with a document. 672 673 @param replaceThis Node to replace. 674 @param withThis Node that is replacing @a replaceThis. 675 @throws Exception When TiXmlNode::ReplaceChild returns Null. 676 677 @see TiXmlNode::ReplaceChild 678 */ 679 Node* ReplaceChild( Node* replaceThis, const Node& withThis ); 680 681 /** 682 Delete a child of this node. 683 684 @param removeThis Node to delete. 685 @throws Exception When removeThis is not a child of this Node. 686 687 @see TiXmlNode::RemoveChild 688 */ 689 void RemoveChild( Node* removeThis ); 690 691 /** 692 Navigate to a sibling node. 693 Wrapper around TiXmlNode::PreviousSibling. 694 695 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 696 @return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false. 697 @throws Exception When TiXmlNode::PreviousSibling returns Null and 'throwIfNoSiblings' is true. 698 */ 699 Node* PreviousSibling( bool throwIfNoSiblings = true ) const; 700 701 /** 702 Navigate to a sibling node with the given @a value. 703 704 @overload 705 @param value The value of the node to look for. 706 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 707 708 @see PreviousSibling( bool throwIfNoSiblings ) 709 */ 710 Node* PreviousSibling( const std::string& value, bool throwIfNoSiblings = true ) const; 711 712 /** 713 @internal 714 Navigate to a sibling node with the given @a value. 715 716 @overload 717 @param value The value of the node to look for. 718 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 719 720 @see PreviousSibling( const std::string& value, bool throwIfNoSiblings ) 721 */ 722 Node* PreviousSibling( const char* value, bool throwIfNoSiblings = true ) const; 723 724 /** 725 Navigate to a sibling node. 726 Wrapper around TiXmlNode::NextSibling. 727 728 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 729 @return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false. 730 @throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true. 731 */ 732 Node* NextSibling( bool throwIfNoSiblings = true ) const; 733 734 /** 735 Navigate to a sibling node with the given @a value. 736 737 @overload 738 @param value The value of the node to look for. 739 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 740 741 @see NextSibling( bool throwIfNoSiblings ) 742 */ 743 Node* NextSibling( const std::string& value, bool throwIfNoSiblings = true ) const; 744 745 /** 746 @internal 747 Navigate to a sibling node with the given @a value. 748 749 @overload 750 @param value The value of the node to look for. 751 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings. 752 753 @see NextSibling( const std::string& value, bool throwIfNoSiblings ) 754 */ 755 Node* NextSibling( const char* value, bool throwIfNoSiblings = true ) const; 756 757 /** 758 @internal 759 Just for Iterator<> 760 761 @param value The value of nodes to iterate through 762 @param next [OUT] The pointer to the first valid node 763 */ 764 template < class T > IterateFirst(const std::string & value,T ** first)765 void IterateFirst( const std::string& value, T** first ) const 766 { 767 *first = 0; 768 for( Node* child = FirstChild( value, false ); child; child = child->NextSibling( value, false ) ) 769 { 770 *first = dynamic_cast< T* >( child ); 771 if ( 0 != *first ) 772 { 773 return; 774 } 775 } 776 } 777 IterateFirst(const std::string &,Attribute **)778 virtual void IterateFirst( const std::string&, Attribute** ) const 779 { 780 TICPPTHROW( "Attributes can only be iterated with Elements." ) 781 } 782 783 /** 784 @internal 785 Just for Iterator<> 786 787 @param value The value of nodes to iterate through 788 @param next [OUT] The pointer to the next valid node 789 */ 790 template < class T > IterateNext(const std::string & value,T ** next)791 void IterateNext( const std::string& value, T** next ) const 792 { 793 Node* sibling = NextSibling( value, false ); 794 *next = dynamic_cast< T* >( sibling ); 795 796 while ( ( 0 != sibling ) && ( 0 == *next ) ) 797 { 798 sibling = sibling->NextSibling( value, false ); 799 *next = dynamic_cast< T* >( sibling ); 800 } 801 } 802 803 /** 804 @internal 805 Just for Iterator<> 806 807 @param value The value of nodes to iterate through 808 @param previous [OUT] The pointer to the previous valid node 809 */ 810 template < class T > IteratePrevious(const std::string & value,T ** previous)811 void IteratePrevious( const std::string& value, T** previous ) const 812 { 813 Node* sibling = PreviousSibling( value, false ); 814 *previous = dynamic_cast< T* >( sibling ); 815 816 while ( ( 0 != sibling ) && ( 0 == *previous ) ) 817 { 818 sibling = sibling->PreviousSibling( value, false ); 819 *previous = dynamic_cast< T* >( sibling ); 820 } 821 } 822 823 /** 824 Navigate to a sibling element. 825 Wrapper around TiXmlNode::NextSibling. 826 827 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling element. 828 @return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false. 829 @throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true. 830 */ 831 Element* NextSiblingElement( bool throwIfNoSiblings = true ) const; 832 833 /** 834 Navigate to a sibling element with the given @a value. 835 836 @overload 837 @param value The value of the element to look for. 838 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements. 839 @see NextSiblingElement( bool throwIfNoSiblings ) 840 */ 841 Element* NextSiblingElement( const std::string& value, bool throwIfNoSiblings = true ) const; 842 843 /** 844 @internal 845 Navigate to a sibling element with the given @a value. 846 847 @overload 848 @param value The value of the element to look for. 849 @param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements. 850 851 @see NextSiblingElement( const std::string& value, bool throwIfNoSiblings ) 852 */ 853 Element* NextSiblingElement( const char* value, bool throwIfNoSiblings = true ) const; 854 855 /** 856 The first child element of this node. 857 858 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children. 859 @return Pointer to child, Null if no element children and 'throwIfNoChildren' is false. 860 @throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChildElement returns Null. 861 862 @see TiXmlNode::FirstChildElement 863 */ 864 Element* FirstChildElement( bool throwIfNoChildren = true ) const; 865 866 /** 867 @internal 868 The first child element of this node with the matching @a value. 869 870 @overload 871 @param value Value to match. 872 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children. 873 874 @see FirstChildElement( bool throwIfNoChildren = true ) 875 */ 876 Element* FirstChildElement( const char* value, bool throwIfNoChildren = true ) const; 877 878 /** 879 The first child element of this node with the matching @a value. 880 881 @overload 882 @param value Value to match. 883 @param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children. 884 885 @see FirstChildElement( const char* value, bool throwIfNoChildren = true ) 886 */ 887 Element* FirstChildElement( const std::string& value, bool throwIfNoChildren = true ) const; 888 889 /** 890 Query the type (as TiXmlNode::NodeType ) of this node. 891 */ 892 int Type() const; 893 894 /** 895 Return a pointer to the Document this node lives in. 896 897 @param throwIfNoDocument [DEF] If true, will throw an exception if this node is not linked under a Document. 898 @return A pointer to the Document this node lives in, NULL if not linked under a Document, and 'throwIfNoDocument' is false. 899 @throws Exception When this node is not linked under a Document and 'throwIfNoDocument' is true. 900 */ 901 Document* GetDocument( bool throwIfNoDocument = true ) const; 902 903 /** 904 Check if this node has no children. 905 906 @return true if this node has no children. 907 */ 908 bool NoChildren() const; 909 910 #ifndef TICPP_NO_RTTI 911 /** 912 Pointer conversion ( NOT OBJECT CONVERSION ) - replaces TiXmlNode::ToElement, TiXmlNode::ToDocument, TiXmlNode::ToComment, etc. 913 914 @throws Exception When the target is not an object of class T 915 @warning Some ancient compilers do not support explicit specification of member template arguments, which this depends on ( e.g. VC6 ). 916 */ 917 template < class T > To()918 T* To() const 919 { 920 T* pointer = dynamic_cast< T* >( this ); 921 if ( 0 == pointer ) 922 { 923 std::string thisType = typeid( this ).name(); 924 std::string targetType = typeid( T ).name(); 925 std::string thatType = typeid( *this ).name(); 926 TICPPTHROW( "The " << thisType.substr( 6 ) << " could not be casted to a " << targetType.substr( 6 ) 927 << " *, because the target object is not a " << targetType.substr( 6 ) << ". (It is a " << thatType.substr( 6 ) << ")" ); 928 } 929 return pointer; 930 } 931 #endif 932 933 /** 934 Pointer conversion - replaces TiXmlNode::ToDocument. 935 936 @throws Exception When this node is not a Document. 937 */ 938 Document* ToDocument() const; 939 940 /** 941 Pointer conversion - replaces TiXmlNode::ToElement. 942 943 @throws Exception When this node is not a Element. 944 */ 945 Element* ToElement() const; 946 947 /** 948 Pointer conversion - replaces TiXmlNode::ToComment. 949 950 @throws Exception When this node is not a Comment. 951 */ 952 Comment* ToComment() const; 953 954 /** 955 Pointer conversion - replaces TiXmlNode::ToText. 956 957 @throws Exception When this node is not a Text. 958 */ 959 Text* ToText() const; 960 961 /** 962 Pointer conversion - replaces TiXmlNode::ToDeclaration. 963 964 @throws Exception When this node is not a Declaration. 965 */ 966 Declaration* ToDeclaration() const; 967 968 /** 969 Pointer conversion - replaces TiXmlNode::ToStylesheetReference. 970 971 @throws Exception When this node is not a StylesheetReference. 972 */ 973 StylesheetReference* ToStylesheetReference() const; 974 975 /** 976 Create an exact duplicate of this node and return it. 977 978 @note Using auto_ptr to manage the memory declared on the heap by TiXmlNode::Clone. 979 @code 980 // Now using clone 981 ticpp::Document doc( "C:\\Test.xml" ); 982 ticpp::Node* sectionToClone; 983 sectionToClone = doc.FirstChild( "settings" ); 984 std::auto_ptr< ticpp::Node > clonedNode = sectionToClone->Clone(); 985 // Now you can use the clone. 986 ticpp::Node* node2 = clonedNode->FirstChildElement()->FirstChild(); 987 ... 988 // After the variable clonedNode goes out of scope it will automatically be cleaned up. 989 @endcode 990 @return Pointer the duplicate node. 991 */ 992 std::auto_ptr< Node > Clone() const; 993 994 /** 995 Accept a hierchical visit the nodes in the TinyXML DOM. 996 @return The boolean returned by the visitor. 997 */ 998 bool Accept( TiXmlVisitor* visitor ) const; 999 1000 /** 1001 Stream input operator. 1002 */ 1003 friend std::istream& operator >>( std::istream& in, Node& base ) 1004 { 1005 in >> *base.GetTiXmlPointer(); 1006 return in; 1007 } 1008 1009 /** 1010 Stream output operator. 1011 */ 1012 friend std::ostream& operator <<( std::ostream& out, const Node& base ) 1013 { 1014 out << *base.GetTiXmlPointer(); 1015 return out; 1016 } 1017 1018 protected: 1019 /** 1020 @internal 1021 Allows NodeImp to use Node*'s. 1022 */ 1023 virtual TiXmlNode* GetTiXmlPointer() const = 0; 1024 GetBasePointer()1025 TiXmlBase* GetBasePointer() const 1026 { 1027 return GetTiXmlPointer(); 1028 } 1029 1030 /** 1031 @internal 1032 Constructs the correct child of Node, based on the Type of the TiXmlNode*. 1033 */ 1034 Node* NodeFactory( TiXmlNode* tiXmlNode, bool throwIfNull = true, bool rememberSpawnedWrapper = true ) const; 1035 1036 }; 1037 1038 /** Iterator for conveniently stepping through Nodes and Attributes. 1039 TinyXML++ introduces iterators: 1040 @code 1041 ticpp::Iterator< ticpp::Node > child; 1042 for ( child = child.begin( parent ); child != child.end(); child++ ) 1043 @endcode 1044 1045 Iterators have the added advantage of filtering by type: 1046 @code 1047 // Only iterates through Comment nodes 1048 ticpp::Iterator< ticpp::Comment > child; 1049 for ( child = child.begin( parent ); child != child.end(); child++ ) 1050 @endcode 1051 1052 @code 1053 // Only iterates through Element nodes with value "ElementValue" 1054 ticpp::Iterator< ticpp::Element > child( "ElementValue" ); 1055 for ( child = child.begin( parent ); child != child.end(); child++ ) 1056 @endcode 1057 1058 Finally, Iterators also work with Attributes 1059 @code 1060 ticpp::Iterator< ticpp::Attribute > attribute; 1061 for ( attribute = attribute.begin( element ); attribute != attribute.end(); attribute++ ) 1062 @endcode 1063 */ 1064 template < class T = Node > 1065 class Iterator 1066 { 1067 private: 1068 T* m_p; /**< Internal Pointer */ 1069 std::string m_value; /**< Value for NextSibling calls */ 1070 1071 public: 1072 1073 /** 1074 For for loop comparisons. 1075 @param parent The parent of the nodes to iterate. 1076 @return The first child of type T. 1077 @code 1078 ticpp::Iterator< ticpp::Node > child; 1079 for ( child = child.begin( parent ); child != child.end(); child++ ) 1080 @endcode 1081 */ begin(const Node * parent)1082 T* begin( const Node* parent ) const 1083 { 1084 T* pointer; 1085 parent->IterateFirst( m_value, &pointer ); 1086 return pointer; 1087 } 1088 1089 /** 1090 For for loop comparisons. 1091 @return NULL 1092 @code 1093 ticpp::Iterator< ticpp::Node > child; 1094 for ( child = child.begin( parent ); child != child.end(); child++ ) 1095 @endcode 1096 */ end()1097 T* end() const 1098 { 1099 return 0; 1100 } 1101 1102 /** Constructor. 1103 @param value If not empty, this iterator will only visit nodes with matching value. 1104 @code 1105 // Only iterates through Element nodes with value "ElementValue" 1106 ticpp::Iterator< ticpp::Element > child( "ElementValue" ); 1107 for ( child = child.begin( parent ); child != child.end(); child++ ) 1108 @endcode 1109 */ 1110 Iterator( const std::string& value = "" ) 1111 : m_p( 0 ), m_value( value ) 1112 { 1113 } 1114 1115 /// Constructor 1116 Iterator( T* node, const std::string& value = "" ) m_p(node)1117 : m_p( node ), m_value( value ) 1118 { 1119 } 1120 1121 /// Constructor Iterator(const Iterator & it)1122 Iterator( const Iterator& it ) 1123 : m_p( it.m_p ), m_value( it.m_value ) 1124 { 1125 } 1126 1127 /** 1128 Gets internal pointer. 1129 @return The internal pointer. 1130 */ Get()1131 T* Get() const 1132 { 1133 return m_p; 1134 } 1135 1136 /** Sets internal pointer */ 1137 Iterator& operator=( const Iterator& it ) 1138 { 1139 m_p = it.m_p; 1140 m_value = it.m_value; 1141 return *this; 1142 } 1143 1144 /** Sets internal pointer */ 1145 Iterator& operator=( T* p ) 1146 { 1147 m_p = p; 1148 return *this; 1149 } 1150 1151 /** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */ 1152 Iterator& operator++() 1153 { 1154 m_p->IterateNext( m_value, &m_p ); 1155 return *this; 1156 } 1157 1158 /** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */ 1159 Iterator operator++(int) 1160 { 1161 Iterator tmp(*this); 1162 ++(*this); 1163 return tmp; 1164 } 1165 1166 /** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */ 1167 Iterator& operator--() 1168 { 1169 m_p->IteratePrevious( m_value, &m_p ); 1170 return *this; 1171 } 1172 1173 /** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */ 1174 Iterator operator--(int) 1175 { 1176 Iterator tmp(*this); 1177 --(*this); 1178 return tmp; 1179 } 1180 1181 /** Compares internal pointer */ 1182 bool operator!=( const T* p ) const 1183 { 1184 if ( m_p == p ) 1185 { 1186 return false; 1187 } 1188 if ( 0 == m_p || 0 == p ) 1189 { 1190 return true; 1191 } 1192 return *m_p != *p; 1193 } 1194 1195 /** Compares internal pointer */ 1196 bool operator!=( const Iterator& it ) const 1197 { 1198 return operator!=( it.m_p ); 1199 } 1200 1201 /** Compares internal pointer* */ 1202 bool operator==( T* p ) const 1203 { 1204 if ( m_p == p ) 1205 { 1206 return true; 1207 } 1208 if ( 0 == m_p || 0 == p ) 1209 { 1210 return false; 1211 } 1212 return *m_p == *p; 1213 } 1214 1215 /** Compares internal pointer */ 1216 bool operator==( const Iterator& it ) const 1217 { 1218 return operator==( it.m_p ); 1219 } 1220 1221 /** So Iterator behaves like a STL iterator */ 1222 T* operator->() const 1223 { 1224 return m_p; 1225 } 1226 1227 /** So Iterator behaves like a STL iterator */ 1228 T& operator*() const 1229 { 1230 return *m_p; 1231 } 1232 }; 1233 1234 /** Implementation of Node wrapper */ 1235 template < class T > 1236 class NodeImp : public Node 1237 { 1238 protected: 1239 1240 T* m_tiXmlPointer; /**< Internal pointer to the TiXml Class which is being wrapped */ 1241 1242 /** 1243 @internal 1244 Gets the internal TinyXML pointer. 1245 1246 @returns The internal TiXmlNode*. 1247 */ GetTiXmlPointer()1248 TiXmlNode* GetTiXmlPointer() const 1249 { 1250 ValidatePointer(); 1251 return m_tiXmlPointer; 1252 } 1253 1254 /** 1255 @internal 1256 Sets the internal pointer. 1257 Saves a copy of the pointer to the RC object. 1258 1259 @param newPointer TiXmlNode* to set. 1260 */ SetTiXmlPointer(T * newPointer)1261 void SetTiXmlPointer( T* newPointer ) 1262 { 1263 m_tiXmlPointer = newPointer; 1264 SetImpRC( newPointer ); 1265 } 1266 1267 /** 1268 @internal 1269 Constructor used by child classes. 1270 */ NodeImp(T * tiXmlPointer)1271 NodeImp( T* tiXmlPointer ) 1272 { 1273 // Check for NULL pointers 1274 if ( 0 == tiXmlPointer ) 1275 { 1276 #ifdef TICPP_NO_RTTI 1277 TICPPTHROW( "Can not create TinyXML objext" ); 1278 #else 1279 TICPPTHROW( "Can not create a " << typeid( T ).name() ); 1280 #endif 1281 } 1282 SetTiXmlPointer( tiXmlPointer ); 1283 m_impRC->IncRef(); 1284 } 1285 1286 /** 1287 @internal 1288 Updates the reference count for the old and new pointers. 1289 In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in. 1290 */ 1291 virtual void operator=( const NodeImp<T>& copy ) 1292 { 1293 // Dropping the reference to the old object 1294 this->m_impRC->DecRef(); 1295 1296 // Pointing to the new Object 1297 SetTiXmlPointer( copy.m_tiXmlPointer ); 1298 1299 // The internal tixml pointer changed in the above line 1300 this->m_impRC->IncRef(); 1301 } 1302 1303 /** 1304 @internal 1305 Updates the reference count for the old and new pointers. 1306 In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in 1307 */ NodeImp(const NodeImp<T> & copy)1308 NodeImp( const NodeImp<T>& copy ) : Node( copy ) 1309 { 1310 // Pointing to the new Object 1311 SetTiXmlPointer( copy.m_tiXmlPointer ); 1312 1313 // The internal tixml pointer changed in the above line 1314 this->m_impRC->IncRef(); 1315 } 1316 1317 public: 1318 1319 /* 1320 Deletes the spawned wrapper objects. 1321 Decrements reference count. 1322 */ ~NodeImp()1323 virtual ~NodeImp() 1324 { 1325 m_impRC->DecRef(); 1326 } 1327 }; 1328 1329 /** Wrapper around TiXmlComment */ 1330 class TICPP_API Comment : public NodeImp< TiXmlComment > 1331 { 1332 public: 1333 1334 /** 1335 Constructor. 1336 */ 1337 Comment(); 1338 1339 /** 1340 Constructor. 1341 */ 1342 Comment( TiXmlComment* comment ); 1343 1344 /** 1345 Constructor. 1346 */ 1347 Comment( const std::string& comment ); 1348 }; 1349 1350 /** Wrapper around TiXmlText */ 1351 class TICPP_API Text : public NodeImp< TiXmlText > 1352 { 1353 public: 1354 1355 /** 1356 Constructor. 1357 */ 1358 Text(); 1359 1360 /** 1361 Constructor. 1362 @overload 1363 */ 1364 Text( TiXmlText* text ); 1365 1366 /** 1367 Constructor. 1368 @overload 1369 */ 1370 Text( const std::string& value ); 1371 1372 /** 1373 Streams value into a string and creates a Text with it. 1374 Uses ToString to covert the parameter to a string. 1375 1376 @param value The value of the Text node. 1377 @throws Exception 1378 1379 @see TiXmlText 1380 */ 1381 template < class T > Text(const T & value)1382 Text( const T& value ) 1383 : NodeImp< TiXmlText >( new TiXmlText( ToString( value ) ) ) 1384 { 1385 m_impRC->InitRef(); 1386 } 1387 }; 1388 1389 /** Wrapper around TiXmlDocument */ 1390 class TICPP_API Document : public NodeImp< TiXmlDocument > 1391 { 1392 public: 1393 /** 1394 Default Constructor. 1395 Create an empty document, that has no name. 1396 */ 1397 Document(); 1398 1399 /** 1400 Constructor. 1401 */ 1402 Document( TiXmlDocument* document ); 1403 1404 /** 1405 Constructor. 1406 */ 1407 Document( const char* documentName ); 1408 1409 /** 1410 * Constructor. 1411 * Create a document with a name. The name of the document is also the filename of the xml. 1412 * @param documentName Name to set in the Document. 1413 * @note LoadFile() needs to be called to actually load the data from the file specified by documentName 1414 * SaveFile() needs to be called to save data to file specified by documentName. 1415 */ 1416 Document( const std::string& documentName ); 1417 1418 /** 1419 Load a file using the current document value. Throws if load is unsuccessful. 1420 1421 @param encoding Sets the documents encoding. 1422 @see TiXmlEncoding 1423 @throws Exception 1424 */ 1425 void LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1426 1427 /** 1428 Save a file using the current document value. Throws if it can't save the file. 1429 1430 @throws Exception 1431 */ 1432 void SaveFile() const; 1433 1434 /** 1435 Load a file using the given filename. Throws if load is unsuccessful. 1436 1437 @param filename File to load. 1438 @param encoding Sets the documents encoding. 1439 @see TiXmlEncoding 1440 @throws Exception 1441 */ 1442 void LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1443 1444 /** 1445 @copydoc Document::LoadFile( const std::string&, TiXmlEncoding ) 1446 */ 1447 void LoadFile( const char* filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1448 1449 /** 1450 Save a file using the given filename. Throws if it can't save the file. 1451 1452 @param filename File to save. 1453 @throws Exception 1454 */ 1455 void SaveFile( const std::string& filename ) const; 1456 1457 /** 1458 Parse the given xml data. 1459 1460 @param xml Xml to parse. 1461 @param throwIfParseError [DEF] If true, throws when there is a parse error. 1462 @param encoding Sets the documents encoding. 1463 @throws Exception 1464 */ 1465 void Parse( const std::string& xml, bool throwIfParseError = true, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1466 }; 1467 1468 /** Wrapper around TiXmlElement */ 1469 class TICPP_API Element : public NodeImp< TiXmlElement > 1470 { 1471 public: 1472 /** 1473 Default Constructor. 1474 */ 1475 Element(); 1476 1477 /** 1478 Default Constructor. Initializes all the variables. 1479 @param value The value of the element. 1480 */ 1481 Element( const std::string& value ); 1482 1483 /** 1484 Default Constructor. Initializes all the variables. 1485 @param value The value of the element. 1486 */ 1487 Element( const char* value ); 1488 1489 /** 1490 Constructor. 1491 */ 1492 Element( TiXmlElement* element ); 1493 1494 /** 1495 Constructor that allows you to set the element text 1496 @param value The value of the element. 1497 @param text The text to set. 1498 */ 1499 template < class T > Element(const std::string & value,const T & text)1500 Element( const std::string& value, const T& text ) 1501 : NodeImp< TiXmlElement >( new TiXmlElement( value ) ) 1502 { 1503 m_impRC->InitRef(); 1504 SetText( text ); 1505 } 1506 1507 /** 1508 Access the first attribute in this element. 1509 1510 @param throwIfNoAttributes [DEF] If true, throws when there are no attributes 1511 @return The first attribute, NULL if there are none and @a throwIfNoAttributes is true 1512 */ 1513 Attribute* FirstAttribute( bool throwIfNoAttributes = true ) const; 1514 1515 /** 1516 Access the last attribute in this element. 1517 1518 @param throwIfNoAttributes [DEF] If true, throws when there are no attributes 1519 @return The last attribute, NULL if there are none and @a throwIfNoAttributes is true 1520 */ 1521 Attribute* LastAttribute( bool throwIfNoAttributes = true ) const; 1522 1523 /** 1524 @internal 1525 Just for Iterator<> 1526 1527 @param value The value of nodes to iterate through 1528 @param next [OUT] The pointer to the first valid node 1529 */ IterateFirst(const std::string &,Attribute ** first)1530 void IterateFirst( const std::string&, Attribute** first ) const 1531 { 1532 *first = 0; 1533 for( Attribute* child = FirstAttribute( false ); child; child = child->Next( false ) ) 1534 { 1535 *first = dynamic_cast< Attribute* >( child ); 1536 if ( 0 != *first ) 1537 { 1538 return; 1539 } 1540 } 1541 } 1542 1543 /** 1544 Sets an attribute of name to a given value. 1545 The attribute will be created if it does not exist, or changed if it does. 1546 Uses ToString to convert the @a value to a string, so there is no need to use any other SetAttribute methods. 1547 1548 @see GetAttribute 1549 */ 1550 template < class T > SetAttribute(const std::string & name,const T & value)1551 void SetAttribute ( const std::string& name, const T& value ) 1552 { 1553 ValidatePointer(); 1554 m_tiXmlPointer->SetAttribute( name, ToString( value ) ); 1555 } 1556 1557 /** 1558 Gets the text of an Element. 1559 1560 @param throwIfNotFound [DEF] If true, will throw an exception if there is no text in this element 1561 @note This only works if the Text is the FirstChild node 1562 @throws Exception When there is no text and throwIfNotFound is true 1563 1564 @see GetText( T* value, bool throwIfNotFound = false ) 1565 @see GetTextOrDefault 1566 @see GetTextOrDefault( T* value, const DefaultT& defaultValue ) 1567 @see TiXmlElement::GetText 1568 */ 1569 std::string GetText( bool throwIfNotFound = true ) const 1570 { 1571 // Get the element's text value as a std::string 1572 std::string temp; 1573 if ( !GetTextImp( &temp ) ) 1574 { 1575 if ( throwIfNotFound ) 1576 { 1577 TICPPTHROW( "Text does not exists in the current element" ); 1578 } 1579 } 1580 1581 return temp; 1582 } 1583 1584 /** 1585 Gets the text of an Element, if it doesn't exist it will return the defaultValue. 1586 1587 @param defaultValue What to put in 'value' if there is no text in this element 1588 @note This only works if the Text is the FirstChild node 1589 1590 @see GetText 1591 @see GetText( T* value, bool throwIfNotFound = false ) 1592 @see GetTextOrDefault( T* value, const DefaultT& defaultValue ) 1593 @see TiXmlElement::GetText 1594 */ GetTextOrDefault(const std::string & defaultValue)1595 std::string GetTextOrDefault( const std::string& defaultValue ) const 1596 { 1597 // Get the element's text value as a std::string 1598 std::string temp; 1599 if ( !GetTextImp( &temp ) ) 1600 { 1601 return defaultValue; 1602 } 1603 1604 return temp; 1605 } 1606 1607 /** 1608 Gets the text value of an Element, if it doesn't exist it will return the defaultValue. 1609 Uses FromString to convert the string to the type of choice 1610 1611 @param value [OUT] The container for the returned value 1612 @param defaultValue What to put in 'value' if there is no text in this element 1613 @note This is different than GetText() in that it will covert the text to what ever type you want. 1614 @note This only works if the Text is the FirstChild node 1615 1616 @see GetText 1617 @see GetText( T* value, bool throwIfNotFound = false ) 1618 @see GetTextOrDefault( const std::string& defaultValue ) 1619 @see TiXmlElement::GetText 1620 */ 1621 template < class T, class DefaultT > GetTextOrDefault(T * value,const DefaultT & defaultValue)1622 void GetTextOrDefault( T* value, const DefaultT& defaultValue ) const 1623 { 1624 // Get the element's text value as a std::string 1625 std::string temp; 1626 if ( !GetTextImp( &temp ) ) 1627 { 1628 // The text value does not exist - set value to the default 1629 *value = defaultValue; 1630 return; 1631 } 1632 1633 // Stream the value from the string to T 1634 FromString( temp, value ); 1635 } 1636 1637 /** 1638 Gets the text of an Element. 1639 Uses FromString to convert the string to the type of choice. 1640 1641 @param value [OUT] The container for the returned value 1642 @param throwIfNotFound [DEF] If true, will throw an exception if there is no text in this element 1643 @note This is different than GetText() in that it will covert the text to what ever type you want 1644 @note This only works if the Text is the FirstChild node 1645 @throws Exception When there is no text and throwIfNotFound is true 1646 1647 @see GetText 1648 @see GetTextOrDefault 1649 @see GetTextOrDefault( T* value, const DefaultT& defaultValue ) 1650 @see TiXmlElement::GetText 1651 */ 1652 template< class T > 1653 void GetText( T* value, bool throwIfNotFound = true ) const 1654 { 1655 // Get the element's text value as a std::string 1656 std::string temp; 1657 if ( !GetTextImp( &temp ) ) 1658 { 1659 if ( throwIfNotFound ) 1660 { 1661 TICPPTHROW( "Text does not exists in the current element" ); 1662 } 1663 else 1664 { 1665 return; 1666 } 1667 } 1668 1669 // Stream the value from the string to T 1670 FromString( temp, value ); 1671 } 1672 1673 /** 1674 Convenience function to set the text of an element. 1675 Creates a Text node and inserts it as the first child. 1676 Uses ToString to convert the parameter to a string. 1677 1678 @param value The text to set. 1679 */ 1680 template < class T > SetText(const T & value)1681 void SetText( const T& value ) 1682 { 1683 ValidatePointer(); 1684 std::string temp = ToString( value ); 1685 1686 if ( m_tiXmlPointer->NoChildren() ) 1687 { 1688 m_tiXmlPointer->LinkEndChild( new TiXmlText( temp ) ); 1689 } 1690 else 1691 { 1692 if ( 0 == m_tiXmlPointer->GetText() ) 1693 { 1694 m_tiXmlPointer->InsertBeforeChild( m_tiXmlPointer->FirstChild(), TiXmlText( temp ) ); 1695 } 1696 else 1697 { 1698 // There already is text, so change it 1699 m_tiXmlPointer->FirstChild()->SetValue( temp ); 1700 } 1701 } 1702 } 1703 1704 /** 1705 Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue. 1706 Uses FromString to convert the string to the type of choice. 1707 1708 @param name The name of the attribute you are querying. 1709 @param value [OUT] The container for the returned value. 1710 @param defaultValue What to put in @a value if there is no attribute in this element. 1711 @throws Exception 1712 1713 @see GetAttribute 1714 */ 1715 template < class T, class DefaulT > GetAttributeOrDefault(const std::string & name,T * value,const DefaulT & defaultValue)1716 void GetAttributeOrDefault( const std::string& name, T* value, const DefaulT& defaultValue ) const 1717 { 1718 // Get the attribute's value as a std::string 1719 std::string temp; 1720 if ( !GetAttributeImp( name, &temp ) ) 1721 { 1722 // The attribute does not exist - set value to the default 1723 *value = defaultValue; 1724 return; 1725 } 1726 1727 // Stream the value from the string to T 1728 FromString( temp, value ); 1729 } 1730 1731 /** 1732 Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue. 1733 1734 @param name The name of the attribute you are querying. 1735 @param defaultValue What to put in @a value if there is no attribute in this element. 1736 1737 @see GetAttribute 1738 */ 1739 std::string GetAttributeOrDefault( const std::string& name, const std::string& defaultValue ) const; 1740 1741 /** 1742 Returns an attribute of @a name from an element. 1743 Uses FromString to convert the string to the type of choice. 1744 1745 @param name The name of the attribute you are querying. 1746 @param throwIfNotFound [DEF] If true, will throw an exception if the attribute doesn't exist 1747 @throws Exception When the attribute doesn't exist and throwIfNotFound is true 1748 @see GetAttributeOrDefault 1749 */ 1750 template < class T > 1751 T GetAttribute( const std::string& name, bool throwIfNotFound = true ) const 1752 { 1753 // Get the attribute's value as a std::string 1754 std::string temp; 1755 T value; 1756 if ( !GetAttributeImp( name, &temp ) ) 1757 { 1758 if ( throwIfNotFound ) 1759 { 1760 const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) ); 1761 TICPPTHROW( error ); 1762 } 1763 } 1764 else 1765 { 1766 // Stream the value from the string to T 1767 FromString( temp, &value ); 1768 } 1769 1770 return value; 1771 } 1772 1773 /** 1774 Gets an attribute of @a name from an element. 1775 Uses FromString to convert the string to the type of choice. 1776 1777 @param name The name of the attribute you are querying. 1778 @param value [OUT] The container for the returned value 1779 @param throwIfNotFound [DEF] If true, will throw an exception if the attribute doesn't exist 1780 @throws Exception When the attribute doesn't exist and throwIfNotFound is true 1781 1782 @see GetAttributeOrDefault 1783 */ 1784 template< class T > 1785 void GetAttribute( const std::string& name, T* value, bool throwIfNotFound = true ) const 1786 { 1787 // Get the attribute's value as a std::string 1788 std::string temp; 1789 if ( !GetAttributeImp( name, &temp ) ) 1790 { 1791 if ( throwIfNotFound ) 1792 { 1793 const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) ); 1794 TICPPTHROW( error ); 1795 } 1796 else 1797 { 1798 return; 1799 } 1800 } 1801 1802 // Stream the value from the string to T 1803 FromString( temp, value ); 1804 } 1805 1806 /** 1807 Gets an attribute of @a name from an element. 1808 Returns an empty string if the attribute does not exist. 1809 1810 @param name The name of the attribute you are querying. 1811 @return The value of the attribute, or an empty string if it does not exist. 1812 1813 @see GetAttributeOrDefault 1814 */ 1815 std::string GetAttribute( const std::string& name ) const; 1816 1817 /** 1818 Returns true, if attribute exists 1819 1820 @param name The name of the attribute you are checking. 1821 @return Existence of attribute 1822 */ 1823 bool HasAttribute( const std::string& name ) const; 1824 1825 /** 1826 Removes attribute from element. 1827 1828 @param name The name of the attribute to remove. 1829 */ 1830 void RemoveAttribute( const std::string& name ); 1831 1832 private: 1833 1834 /** 1835 @internal 1836 Implimentation of the GetAttribute and GetAttributeOrDefault template methods. 1837 */ 1838 bool GetAttributeImp( const std::string& name, std::string* value ) const; 1839 1840 /** 1841 @internal 1842 Implimentation of the GetText, GetTextOrDefault, GetTextValue, and GetTextValueOrDefault template methods. 1843 */ 1844 bool GetTextImp( std::string* value ) const; 1845 }; 1846 1847 /** Wrapper around TiXmlDeclaration */ 1848 class TICPP_API Declaration : public NodeImp< TiXmlDeclaration > 1849 { 1850 public: 1851 /** 1852 Default Constructor. Construct an empty declaration. 1853 */ 1854 Declaration(); 1855 1856 /** 1857 Constructor. 1858 */ 1859 Declaration( TiXmlDeclaration* declaration ); 1860 1861 /** 1862 Constructor. 1863 */ 1864 Declaration( const std::string& version, const std::string& encoding, const std::string& standalone ); 1865 1866 /** 1867 Version. Will return an empty string if none was found. 1868 */ 1869 std::string Version() const; 1870 1871 /** 1872 Encoding. Will return an empty string if none was found. 1873 */ 1874 std::string Encoding() const; 1875 1876 /** 1877 StandAlone. Is this a standalone document? 1878 */ 1879 std::string Standalone() const; 1880 }; 1881 1882 /** Wrapper around TiXmlStylesheetReference */ 1883 class TICPP_API StylesheetReference : public NodeImp< TiXmlStylesheetReference > 1884 { 1885 public: 1886 /** 1887 Default Constructor. Construct an empty declaration. 1888 */ 1889 StylesheetReference(); 1890 1891 /** 1892 Constructor. 1893 */ 1894 StylesheetReference( TiXmlStylesheetReference* stylesheetReference ); 1895 1896 /** 1897 Constructor. 1898 */ 1899 StylesheetReference( const std::string& type, const std::string& href ); 1900 1901 /** 1902 Type. Will return an empty string if none was found. 1903 */ 1904 std::string Type() const; 1905 1906 /** 1907 Href. Will return an empty string if none was found. 1908 */ 1909 std::string Href() const; 1910 }; 1911 } 1912 1913 #endif // TICPP_INCLUDED 1914