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