tinyxml2.h (73173B)
1 /* 2 Original code by Lee Thomason (www.grinninglizard.com) 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any 6 damages arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any 9 purpose, including commercial applications, and to alter it and 10 redistribute it freely, subject to the following restrictions: 11 12 1. The origin of this software must not be misrepresented; you must 13 not claim that you wrote the original software. If you use this 14 software in a product, an acknowledgment in the product documentation 15 would be appreciated but is not required. 16 17 2. Altered source versions must be plainly marked as such, and 18 must not be misrepresented as being the original software. 19 20 3. This notice may not be removed or altered from any source 21 distribution. 22 */ 23 24 #ifndef TINYXML2_INCLUDED 25 #define TINYXML2_INCLUDED 26 27 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) 28 # include <ctype.h> 29 # include <limits.h> 30 # include <stdio.h> 31 # include <stdlib.h> 32 # include <string.h> 33 # if defined(__PS3__) 34 # include <stddef.h> 35 # endif 36 #else 37 # include <cctype> 38 # include <climits> 39 # include <cstdio> 40 # include <cstdlib> 41 # include <cstring> 42 #endif 43 #include <stdint.h> 44 45 /* 46 TODO: intern strings instead of allocation. 47 */ 48 /* 49 gcc: 50 g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe 51 52 Formatting, Artistic Style: 53 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h 54 */ 55 56 #if defined( _DEBUG ) || defined (__DEBUG__) 57 # ifndef TINYXML2_DEBUG 58 # define TINYXML2_DEBUG 59 # endif 60 #endif 61 62 #ifdef _MSC_VER 63 # pragma warning(push) 64 # pragma warning(disable: 4251) 65 #endif 66 67 #ifdef _WIN32 68 # ifdef TINYXML2_EXPORT 69 # define TINYXML2_LIB __declspec(dllexport) 70 # elif defined(TINYXML2_IMPORT) 71 # define TINYXML2_LIB __declspec(dllimport) 72 # else 73 # define TINYXML2_LIB 74 # endif 75 #elif __GNUC__ >= 4 76 # define TINYXML2_LIB __attribute__((visibility("default"))) 77 #else 78 # define TINYXML2_LIB 79 #endif 80 81 82 #if defined(TINYXML2_DEBUG) 83 # if defined(_MSC_VER) 84 # // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like 85 # define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } 86 # elif defined (ANDROID_NDK) 87 # include <android/log.h> 88 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } 89 # else 90 # include <assert.h> 91 # define TIXMLASSERT assert 92 # endif 93 #else 94 # define TIXMLASSERT( x ) {} 95 #endif 96 97 98 /* Versioning, past 1.0.14: 99 http://semver.org/ 100 */ 101 static const int TIXML2_MAJOR_VERSION = 8; 102 static const int TIXML2_MINOR_VERSION = 0; 103 static const int TIXML2_PATCH_VERSION = 0; 104 105 #define TINYXML2_MAJOR_VERSION 8 106 #define TINYXML2_MINOR_VERSION 0 107 #define TINYXML2_PATCH_VERSION 0 108 109 // A fixed element depth limit is problematic. There needs to be a 110 // limit to avoid a stack overflow. However, that limit varies per 111 // system, and the capacity of the stack. On the other hand, it's a trivial 112 // attack that can result from ill, malicious, or even correctly formed XML, 113 // so there needs to be a limit in place. 114 static const int TINYXML2_MAX_ELEMENT_DEPTH = 200; 115 116 namespace tinyxml2 117 { 118 class XMLDocument; 119 class XMLElement; 120 class XMLAttribute; 121 class XMLComment; 122 class XMLText; 123 class XMLDeclaration; 124 class XMLUnknown; 125 class XMLPrinter; 126 127 /* 128 A class that wraps strings. Normally stores the start and end 129 pointers into the XML file itself, and will apply normalization 130 and entity translation if actually read. Can also store (and memory 131 manage) a traditional char[] 132 133 Isn't clear why TINYXML2_LIB is needed; but seems to fix #719 134 */ 135 class TINYXML2_LIB StrPair 136 { 137 public: 138 enum { 139 NEEDS_ENTITY_PROCESSING = 0x01, 140 NEEDS_NEWLINE_NORMALIZATION = 0x02, 141 NEEDS_WHITESPACE_COLLAPSING = 0x04, 142 143 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 144 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 145 ATTRIBUTE_NAME = 0, 146 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 147 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 148 COMMENT = NEEDS_NEWLINE_NORMALIZATION 149 }; 150 151 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} 152 ~StrPair(); 153 154 void Set( char* start, char* end, int flags ) { 155 TIXMLASSERT( start ); 156 TIXMLASSERT( end ); 157 Reset(); 158 _start = start; 159 _end = end; 160 _flags = flags | NEEDS_FLUSH; 161 } 162 163 const char* GetStr(); 164 165 bool Empty() const { 166 return _start == _end; 167 } 168 169 void SetInternedStr( const char* str ) { 170 Reset(); 171 _start = const_cast<char*>(str); 172 } 173 174 void SetStr( const char* str, int flags=0 ); 175 176 char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr ); 177 char* ParseName( char* in ); 178 179 void TransferTo( StrPair* other ); 180 void Reset(); 181 182 private: 183 void CollapseWhitespace(); 184 185 enum { 186 NEEDS_FLUSH = 0x100, 187 NEEDS_DELETE = 0x200 188 }; 189 190 int _flags; 191 char* _start; 192 char* _end; 193 194 StrPair( const StrPair& other ); // not supported 195 void operator=( const StrPair& other ); // not supported, use TransferTo() 196 }; 197 198 199 /* 200 A dynamic array of Plain Old Data. Doesn't support constructors, etc. 201 Has a small initial memory pool, so that low or no usage will not 202 cause a call to new/delete 203 */ 204 template <class T, int INITIAL_SIZE> 205 class DynArray 206 { 207 public: 208 DynArray() : 209 _mem( _pool ), 210 _allocated( INITIAL_SIZE ), 211 _size( 0 ) 212 { 213 } 214 215 ~DynArray() { 216 if ( _mem != _pool ) { 217 delete [] _mem; 218 } 219 } 220 221 void Clear() { 222 _size = 0; 223 } 224 225 void Push( T t ) { 226 TIXMLASSERT( _size < INT_MAX ); 227 EnsureCapacity( _size+1 ); 228 _mem[_size] = t; 229 ++_size; 230 } 231 232 T* PushArr( int count ) { 233 TIXMLASSERT( count >= 0 ); 234 TIXMLASSERT( _size <= INT_MAX - count ); 235 EnsureCapacity( _size+count ); 236 T* ret = &_mem[_size]; 237 _size += count; 238 return ret; 239 } 240 241 T Pop() { 242 TIXMLASSERT( _size > 0 ); 243 --_size; 244 return _mem[_size]; 245 } 246 247 void PopArr( int count ) { 248 TIXMLASSERT( _size >= count ); 249 _size -= count; 250 } 251 252 bool Empty() const { 253 return _size == 0; 254 } 255 256 T& operator[](int i) { 257 TIXMLASSERT( i>= 0 && i < _size ); 258 return _mem[i]; 259 } 260 261 const T& operator[](int i) const { 262 TIXMLASSERT( i>= 0 && i < _size ); 263 return _mem[i]; 264 } 265 266 const T& PeekTop() const { 267 TIXMLASSERT( _size > 0 ); 268 return _mem[ _size - 1]; 269 } 270 271 int Size() const { 272 TIXMLASSERT( _size >= 0 ); 273 return _size; 274 } 275 276 int Capacity() const { 277 TIXMLASSERT( _allocated >= INITIAL_SIZE ); 278 return _allocated; 279 } 280 281 void SwapRemove(int i) { 282 TIXMLASSERT(i >= 0 && i < _size); 283 TIXMLASSERT(_size > 0); 284 _mem[i] = _mem[_size - 1]; 285 --_size; 286 } 287 288 const T* Mem() const { 289 TIXMLASSERT( _mem ); 290 return _mem; 291 } 292 293 T* Mem() { 294 TIXMLASSERT( _mem ); 295 return _mem; 296 } 297 298 private: 299 DynArray( const DynArray& ); // not supported 300 void operator=( const DynArray& ); // not supported 301 302 void EnsureCapacity( int cap ) { 303 TIXMLASSERT( cap > 0 ); 304 if ( cap > _allocated ) { 305 TIXMLASSERT( cap <= INT_MAX / 2 ); 306 const int newAllocated = cap * 2; 307 T* newMem = new T[newAllocated]; 308 TIXMLASSERT( newAllocated >= _size ); 309 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs 310 if ( _mem != _pool ) { 311 delete [] _mem; 312 } 313 _mem = newMem; 314 _allocated = newAllocated; 315 } 316 } 317 318 T* _mem; 319 T _pool[INITIAL_SIZE]; 320 int _allocated; // objects allocated 321 int _size; // number objects in use 322 }; 323 324 325 /* 326 Parent virtual class of a pool for fast allocation 327 and deallocation of objects. 328 */ 329 class MemPool 330 { 331 public: 332 MemPool() {} 333 virtual ~MemPool() {} 334 335 virtual int ItemSize() const = 0; 336 virtual void* Alloc() = 0; 337 virtual void Free( void* ) = 0; 338 virtual void SetTracked() = 0; 339 }; 340 341 342 /* 343 Template child class to create pools of the correct type. 344 */ 345 template< int ITEM_SIZE > 346 class MemPoolT : public MemPool 347 { 348 public: 349 MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} 350 ~MemPoolT() { 351 MemPoolT< ITEM_SIZE >::Clear(); 352 } 353 354 void Clear() { 355 // Delete the blocks. 356 while( !_blockPtrs.Empty()) { 357 Block* lastBlock = _blockPtrs.Pop(); 358 delete lastBlock; 359 } 360 _root = 0; 361 _currentAllocs = 0; 362 _nAllocs = 0; 363 _maxAllocs = 0; 364 _nUntracked = 0; 365 } 366 367 virtual int ItemSize() const { 368 return ITEM_SIZE; 369 } 370 int CurrentAllocs() const { 371 return _currentAllocs; 372 } 373 374 virtual void* Alloc() { 375 if ( !_root ) { 376 // Need a new block. 377 Block* block = new Block(); 378 _blockPtrs.Push( block ); 379 380 Item* blockItems = block->items; 381 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) { 382 blockItems[i].next = &(blockItems[i + 1]); 383 } 384 blockItems[ITEMS_PER_BLOCK - 1].next = 0; 385 _root = blockItems; 386 } 387 Item* const result = _root; 388 TIXMLASSERT( result != 0 ); 389 _root = _root->next; 390 391 ++_currentAllocs; 392 if ( _currentAllocs > _maxAllocs ) { 393 _maxAllocs = _currentAllocs; 394 } 395 ++_nAllocs; 396 ++_nUntracked; 397 return result; 398 } 399 400 virtual void Free( void* mem ) { 401 if ( !mem ) { 402 return; 403 } 404 --_currentAllocs; 405 Item* item = static_cast<Item*>( mem ); 406 #ifdef TINYXML2_DEBUG 407 memset( item, 0xfe, sizeof( *item ) ); 408 #endif 409 item->next = _root; 410 _root = item; 411 } 412 void Trace( const char* name ) { 413 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", 414 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs, 415 ITEM_SIZE, _nAllocs, _blockPtrs.Size() ); 416 } 417 418 void SetTracked() { 419 --_nUntracked; 420 } 421 422 int Untracked() const { 423 return _nUntracked; 424 } 425 426 // This number is perf sensitive. 4k seems like a good tradeoff on my machine. 427 // The test file is large, 170k. 428 // Release: VS2010 gcc(no opt) 429 // 1k: 4000 430 // 2k: 4000 431 // 4k: 3900 21000 432 // 16k: 5200 433 // 32k: 4300 434 // 64k: 4000 21000 435 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK 436 // in private part if ITEMS_PER_BLOCK is private 437 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE }; 438 439 private: 440 MemPoolT( const MemPoolT& ); // not supported 441 void operator=( const MemPoolT& ); // not supported 442 443 union Item { 444 Item* next; 445 char itemData[ITEM_SIZE]; 446 }; 447 struct Block { 448 Item items[ITEMS_PER_BLOCK]; 449 }; 450 DynArray< Block*, 10 > _blockPtrs; 451 Item* _root; 452 453 int _currentAllocs; 454 int _nAllocs; 455 int _maxAllocs; 456 int _nUntracked; 457 }; 458 459 460 461 /** 462 Implements the interface to the "Visitor pattern" (see the Accept() method.) 463 If you call the Accept() method, it requires being passed a XMLVisitor 464 class to handle callbacks. For nodes that contain other nodes (Document, Element) 465 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs 466 are simply called with Visit(). 467 468 If you return 'true' from a Visit method, recursive parsing will continue. If you return 469 false, <b>no children of this node or its siblings</b> will be visited. 470 471 All flavors of Visit methods have a default implementation that returns 'true' (continue 472 visiting). You need to only override methods that are interesting to you. 473 474 Generally Accept() is called on the XMLDocument, although all nodes support visiting. 475 476 You should never change the document from a callback. 477 478 @sa XMLNode::Accept() 479 */ 480 class TINYXML2_LIB XMLVisitor 481 { 482 public: 483 virtual ~XMLVisitor() {} 484 485 /// Visit a document. 486 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { 487 return true; 488 } 489 /// Visit a document. 490 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { 491 return true; 492 } 493 494 /// Visit an element. 495 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { 496 return true; 497 } 498 /// Visit an element. 499 virtual bool VisitExit( const XMLElement& /*element*/ ) { 500 return true; 501 } 502 503 /// Visit a declaration. 504 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { 505 return true; 506 } 507 /// Visit a text node. 508 virtual bool Visit( const XMLText& /*text*/ ) { 509 return true; 510 } 511 /// Visit a comment node. 512 virtual bool Visit( const XMLComment& /*comment*/ ) { 513 return true; 514 } 515 /// Visit an unknown node. 516 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { 517 return true; 518 } 519 }; 520 521 // WARNING: must match XMLDocument::_errorNames[] 522 enum XMLError { 523 XML_SUCCESS = 0, 524 XML_NO_ATTRIBUTE, 525 XML_WRONG_ATTRIBUTE_TYPE, 526 XML_ERROR_FILE_NOT_FOUND, 527 XML_ERROR_FILE_COULD_NOT_BE_OPENED, 528 XML_ERROR_FILE_READ_ERROR, 529 XML_ERROR_PARSING_ELEMENT, 530 XML_ERROR_PARSING_ATTRIBUTE, 531 XML_ERROR_PARSING_TEXT, 532 XML_ERROR_PARSING_CDATA, 533 XML_ERROR_PARSING_COMMENT, 534 XML_ERROR_PARSING_DECLARATION, 535 XML_ERROR_PARSING_UNKNOWN, 536 XML_ERROR_EMPTY_DOCUMENT, 537 XML_ERROR_MISMATCHED_ELEMENT, 538 XML_ERROR_PARSING, 539 XML_CAN_NOT_CONVERT_TEXT, 540 XML_NO_TEXT_NODE, 541 XML_ELEMENT_DEPTH_EXCEEDED, 542 543 XML_ERROR_COUNT 544 }; 545 546 547 /* 548 Utility functionality. 549 */ 550 class TINYXML2_LIB XMLUtil 551 { 552 public: 553 static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { 554 TIXMLASSERT( p ); 555 556 while( IsWhiteSpace(*p) ) { 557 if (curLineNumPtr && *p == '\n') { 558 ++(*curLineNumPtr); 559 } 560 ++p; 561 } 562 TIXMLASSERT( p ); 563 return p; 564 } 565 static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) { 566 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) ); 567 } 568 569 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't 570 // correct, but simple, and usually works. 571 static bool IsWhiteSpace( char p ) { 572 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) ); 573 } 574 575 inline static bool IsNameStartChar( unsigned char ch ) { 576 if ( ch >= 128 ) { 577 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() 578 return true; 579 } 580 if ( isalpha( ch ) ) { 581 return true; 582 } 583 return ch == ':' || ch == '_'; 584 } 585 586 inline static bool IsNameChar( unsigned char ch ) { 587 return IsNameStartChar( ch ) 588 || isdigit( ch ) 589 || ch == '.' 590 || ch == '-'; 591 } 592 593 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { 594 if ( p == q ) { 595 return true; 596 } 597 TIXMLASSERT( p ); 598 TIXMLASSERT( q ); 599 TIXMLASSERT( nChar >= 0 ); 600 return strncmp( p, q, nChar ) == 0; 601 } 602 603 inline static bool IsUTF8Continuation( const char p ) { 604 return ( p & 0x80 ) != 0; 605 } 606 607 static const char* ReadBOM( const char* p, bool* hasBOM ); 608 // p is the starting location, 609 // the UTF-8 value of the entity will be placed in value, and length filled in. 610 static const char* GetCharacterRef( const char* p, char* value, int* length ); 611 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); 612 613 // converts primitive types to strings 614 static void ToStr( int v, char* buffer, int bufferSize ); 615 static void ToStr( unsigned v, char* buffer, int bufferSize ); 616 static void ToStr( bool v, char* buffer, int bufferSize ); 617 static void ToStr( float v, char* buffer, int bufferSize ); 618 static void ToStr( double v, char* buffer, int bufferSize ); 619 static void ToStr(int64_t v, char* buffer, int bufferSize); 620 static void ToStr(uint64_t v, char* buffer, int bufferSize); 621 622 // converts strings to primitive types 623 static bool ToInt( const char* str, int* value ); 624 static bool ToUnsigned( const char* str, unsigned* value ); 625 static bool ToBool( const char* str, bool* value ); 626 static bool ToFloat( const char* str, float* value ); 627 static bool ToDouble( const char* str, double* value ); 628 static bool ToInt64(const char* str, int64_t* value); 629 static bool ToUnsigned64(const char* str, uint64_t* value); 630 // Changes what is serialized for a boolean value. 631 // Default to "true" and "false". Shouldn't be changed 632 // unless you have a special testing or compatibility need. 633 // Be careful: static, global, & not thread safe. 634 // Be sure to set static const memory as parameters. 635 static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); 636 637 private: 638 static const char* writeBoolTrue; 639 static const char* writeBoolFalse; 640 }; 641 642 643 /** XMLNode is a base class for every object that is in the 644 XML Document Object Model (DOM), except XMLAttributes. 645 Nodes have siblings, a parent, and children which can 646 be navigated. A node is always in a XMLDocument. 647 The type of a XMLNode can be queried, and it can 648 be cast to its more defined type. 649 650 A XMLDocument allocates memory for all its Nodes. 651 When the XMLDocument gets deleted, all its Nodes 652 will also be deleted. 653 654 @verbatim 655 A Document can contain: Element (container or leaf) 656 Comment (leaf) 657 Unknown (leaf) 658 Declaration( leaf ) 659 660 An Element can contain: Element (container or leaf) 661 Text (leaf) 662 Attributes (not on tree) 663 Comment (leaf) 664 Unknown (leaf) 665 666 @endverbatim 667 */ 668 class TINYXML2_LIB XMLNode 669 { 670 friend class XMLDocument; 671 friend class XMLElement; 672 public: 673 674 /// Get the XMLDocument that owns this XMLNode. 675 const XMLDocument* GetDocument() const { 676 TIXMLASSERT( _document ); 677 return _document; 678 } 679 /// Get the XMLDocument that owns this XMLNode. 680 XMLDocument* GetDocument() { 681 TIXMLASSERT( _document ); 682 return _document; 683 } 684 685 /// Safely cast to an Element, or null. 686 virtual XMLElement* ToElement() { 687 return 0; 688 } 689 /// Safely cast to Text, or null. 690 virtual XMLText* ToText() { 691 return 0; 692 } 693 /// Safely cast to a Comment, or null. 694 virtual XMLComment* ToComment() { 695 return 0; 696 } 697 /// Safely cast to a Document, or null. 698 virtual XMLDocument* ToDocument() { 699 return 0; 700 } 701 /// Safely cast to a Declaration, or null. 702 virtual XMLDeclaration* ToDeclaration() { 703 return 0; 704 } 705 /// Safely cast to an Unknown, or null. 706 virtual XMLUnknown* ToUnknown() { 707 return 0; 708 } 709 710 virtual const XMLElement* ToElement() const { 711 return 0; 712 } 713 virtual const XMLText* ToText() const { 714 return 0; 715 } 716 virtual const XMLComment* ToComment() const { 717 return 0; 718 } 719 virtual const XMLDocument* ToDocument() const { 720 return 0; 721 } 722 virtual const XMLDeclaration* ToDeclaration() const { 723 return 0; 724 } 725 virtual const XMLUnknown* ToUnknown() const { 726 return 0; 727 } 728 729 /** The meaning of 'value' changes for the specific type. 730 @verbatim 731 Document: empty (NULL is returned, not an empty string) 732 Element: name of the element 733 Comment: the comment text 734 Unknown: the tag contents 735 Text: the text string 736 @endverbatim 737 */ 738 const char* Value() const; 739 740 /** Set the Value of an XML node. 741 @sa Value() 742 */ 743 void SetValue( const char* val, bool staticMem=false ); 744 745 /// Gets the line number the node is in, if the document was parsed from a file. 746 int GetLineNum() const { return _parseLineNum; } 747 748 /// Get the parent of this node on the DOM. 749 const XMLNode* Parent() const { 750 return _parent; 751 } 752 753 XMLNode* Parent() { 754 return _parent; 755 } 756 757 /// Returns true if this node has no children. 758 bool NoChildren() const { 759 return !_firstChild; 760 } 761 762 /// Get the first child node, or null if none exists. 763 const XMLNode* FirstChild() const { 764 return _firstChild; 765 } 766 767 XMLNode* FirstChild() { 768 return _firstChild; 769 } 770 771 /** Get the first child element, or optionally the first child 772 element with the specified name. 773 */ 774 const XMLElement* FirstChildElement( const char* name = 0 ) const; 775 776 XMLElement* FirstChildElement( const char* name = 0 ) { 777 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name )); 778 } 779 780 /// Get the last child node, or null if none exists. 781 const XMLNode* LastChild() const { 782 return _lastChild; 783 } 784 785 XMLNode* LastChild() { 786 return _lastChild; 787 } 788 789 /** Get the last child element or optionally the last child 790 element with the specified name. 791 */ 792 const XMLElement* LastChildElement( const char* name = 0 ) const; 793 794 XMLElement* LastChildElement( const char* name = 0 ) { 795 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) ); 796 } 797 798 /// Get the previous (left) sibling node of this node. 799 const XMLNode* PreviousSibling() const { 800 return _prev; 801 } 802 803 XMLNode* PreviousSibling() { 804 return _prev; 805 } 806 807 /// Get the previous (left) sibling element of this node, with an optionally supplied name. 808 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; 809 810 XMLElement* PreviousSiblingElement( const char* name = 0 ) { 811 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) ); 812 } 813 814 /// Get the next (right) sibling node of this node. 815 const XMLNode* NextSibling() const { 816 return _next; 817 } 818 819 XMLNode* NextSibling() { 820 return _next; 821 } 822 823 /// Get the next (right) sibling element of this node, with an optionally supplied name. 824 const XMLElement* NextSiblingElement( const char* name = 0 ) const; 825 826 XMLElement* NextSiblingElement( const char* name = 0 ) { 827 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) ); 828 } 829 830 /** 831 Add a child node as the last (right) child. 832 If the child node is already part of the document, 833 it is moved from its old location to the new location. 834 Returns the addThis argument or 0 if the node does not 835 belong to the same document. 836 */ 837 XMLNode* InsertEndChild( XMLNode* addThis ); 838 839 XMLNode* LinkEndChild( XMLNode* addThis ) { 840 return InsertEndChild( addThis ); 841 } 842 /** 843 Add a child node as the first (left) child. 844 If the child node is already part of the document, 845 it is moved from its old location to the new location. 846 Returns the addThis argument or 0 if the node does not 847 belong to the same document. 848 */ 849 XMLNode* InsertFirstChild( XMLNode* addThis ); 850 /** 851 Add a node after the specified child node. 852 If the child node is already part of the document, 853 it is moved from its old location to the new location. 854 Returns the addThis argument or 0 if the afterThis node 855 is not a child of this node, or if the node does not 856 belong to the same document. 857 */ 858 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); 859 860 /** 861 Delete all the children of this node. 862 */ 863 void DeleteChildren(); 864 865 /** 866 Delete a child of this node. 867 */ 868 void DeleteChild( XMLNode* node ); 869 870 /** 871 Make a copy of this node, but not its children. 872 You may pass in a Document pointer that will be 873 the owner of the new Node. If the 'document' is 874 null, then the node returned will be allocated 875 from the current Document. (this->GetDocument()) 876 877 Note: if called on a XMLDocument, this will return null. 878 */ 879 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; 880 881 /** 882 Make a copy of this node and all its children. 883 884 If the 'target' is null, then the nodes will 885 be allocated in the current document. If 'target' 886 is specified, the memory will be allocated is the 887 specified XMLDocument. 888 889 NOTE: This is probably not the correct tool to 890 copy a document, since XMLDocuments can have multiple 891 top level XMLNodes. You probably want to use 892 XMLDocument::DeepCopy() 893 */ 894 XMLNode* DeepClone( XMLDocument* target ) const; 895 896 /** 897 Test if 2 nodes are the same, but don't test children. 898 The 2 nodes do not need to be in the same Document. 899 900 Note: if called on a XMLDocument, this will return false. 901 */ 902 virtual bool ShallowEqual( const XMLNode* compare ) const = 0; 903 904 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the 905 XML tree will be conditionally visited and the host will be called back 906 via the XMLVisitor interface. 907 908 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse 909 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this 910 interface versus any other.) 911 912 The interface has been based on ideas from: 913 914 - http://www.saxproject.org/ 915 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern 916 917 Which are both good references for "visiting". 918 919 An example of using Accept(): 920 @verbatim 921 XMLPrinter printer; 922 tinyxmlDoc.Accept( &printer ); 923 const char* xmlcstr = printer.CStr(); 924 @endverbatim 925 */ 926 virtual bool Accept( XMLVisitor* visitor ) const = 0; 927 928 /** 929 Set user data into the XMLNode. TinyXML-2 in 930 no way processes or interprets user data. 931 It is initially 0. 932 */ 933 void SetUserData(void* userData) { _userData = userData; } 934 935 /** 936 Get user data set into the XMLNode. TinyXML-2 in 937 no way processes or interprets user data. 938 It is initially 0. 939 */ 940 void* GetUserData() const { return _userData; } 941 942 protected: 943 explicit XMLNode( XMLDocument* ); 944 virtual ~XMLNode(); 945 946 virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); 947 948 XMLDocument* _document; 949 XMLNode* _parent; 950 mutable StrPair _value; 951 int _parseLineNum; 952 953 XMLNode* _firstChild; 954 XMLNode* _lastChild; 955 956 XMLNode* _prev; 957 XMLNode* _next; 958 959 void* _userData; 960 961 private: 962 MemPool* _memPool; 963 void Unlink( XMLNode* child ); 964 static void DeleteNode( XMLNode* node ); 965 void InsertChildPreamble( XMLNode* insertThis ) const; 966 const XMLElement* ToElementWithName( const char* name ) const; 967 968 XMLNode( const XMLNode& ); // not supported 969 XMLNode& operator=( const XMLNode& ); // not supported 970 }; 971 972 973 /** XML text. 974 975 Note that a text node can have child element nodes, for example: 976 @verbatim 977 <root>This is <b>bold</b></root> 978 @endverbatim 979 980 A text node can have 2 ways to output the next. "normal" output 981 and CDATA. It will default to the mode it was parsed from the XML file and 982 you generally want to leave it alone, but you can change the output mode with 983 SetCData() and query it with CData(). 984 */ 985 class TINYXML2_LIB XMLText : public XMLNode 986 { 987 friend class XMLDocument; 988 public: 989 virtual bool Accept( XMLVisitor* visitor ) const; 990 991 virtual XMLText* ToText() { 992 return this; 993 } 994 virtual const XMLText* ToText() const { 995 return this; 996 } 997 998 /// Declare whether this should be CDATA or standard text. 999 void SetCData( bool isCData ) { 1000 _isCData = isCData; 1001 } 1002 /// Returns true if this is a CDATA text element. 1003 bool CData() const { 1004 return _isCData; 1005 } 1006 1007 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1008 virtual bool ShallowEqual( const XMLNode* compare ) const; 1009 1010 protected: 1011 explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} 1012 virtual ~XMLText() {} 1013 1014 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); 1015 1016 private: 1017 bool _isCData; 1018 1019 XMLText( const XMLText& ); // not supported 1020 XMLText& operator=( const XMLText& ); // not supported 1021 }; 1022 1023 1024 /** An XML Comment. */ 1025 class TINYXML2_LIB XMLComment : public XMLNode 1026 { 1027 friend class XMLDocument; 1028 public: 1029 virtual XMLComment* ToComment() { 1030 return this; 1031 } 1032 virtual const XMLComment* ToComment() const { 1033 return this; 1034 } 1035 1036 virtual bool Accept( XMLVisitor* visitor ) const; 1037 1038 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1039 virtual bool ShallowEqual( const XMLNode* compare ) const; 1040 1041 protected: 1042 explicit XMLComment( XMLDocument* doc ); 1043 virtual ~XMLComment(); 1044 1045 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); 1046 1047 private: 1048 XMLComment( const XMLComment& ); // not supported 1049 XMLComment& operator=( const XMLComment& ); // not supported 1050 }; 1051 1052 1053 /** In correct XML the declaration is the first entry in the file. 1054 @verbatim 1055 <?xml version="1.0" standalone="yes"?> 1056 @endverbatim 1057 1058 TinyXML-2 will happily read or write files without a declaration, 1059 however. 1060 1061 The text of the declaration isn't interpreted. It is parsed 1062 and written as a string. 1063 */ 1064 class TINYXML2_LIB XMLDeclaration : public XMLNode 1065 { 1066 friend class XMLDocument; 1067 public: 1068 virtual XMLDeclaration* ToDeclaration() { 1069 return this; 1070 } 1071 virtual const XMLDeclaration* ToDeclaration() const { 1072 return this; 1073 } 1074 1075 virtual bool Accept( XMLVisitor* visitor ) const; 1076 1077 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1078 virtual bool ShallowEqual( const XMLNode* compare ) const; 1079 1080 protected: 1081 explicit XMLDeclaration( XMLDocument* doc ); 1082 virtual ~XMLDeclaration(); 1083 1084 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); 1085 1086 private: 1087 XMLDeclaration( const XMLDeclaration& ); // not supported 1088 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported 1089 }; 1090 1091 1092 /** Any tag that TinyXML-2 doesn't recognize is saved as an 1093 unknown. It is a tag of text, but should not be modified. 1094 It will be written back to the XML, unchanged, when the file 1095 is saved. 1096 1097 DTD tags get thrown into XMLUnknowns. 1098 */ 1099 class TINYXML2_LIB XMLUnknown : public XMLNode 1100 { 1101 friend class XMLDocument; 1102 public: 1103 virtual XMLUnknown* ToUnknown() { 1104 return this; 1105 } 1106 virtual const XMLUnknown* ToUnknown() const { 1107 return this; 1108 } 1109 1110 virtual bool Accept( XMLVisitor* visitor ) const; 1111 1112 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1113 virtual bool ShallowEqual( const XMLNode* compare ) const; 1114 1115 protected: 1116 explicit XMLUnknown( XMLDocument* doc ); 1117 virtual ~XMLUnknown(); 1118 1119 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); 1120 1121 private: 1122 XMLUnknown( const XMLUnknown& ); // not supported 1123 XMLUnknown& operator=( const XMLUnknown& ); // not supported 1124 }; 1125 1126 1127 1128 /** An attribute is a name-value pair. Elements have an arbitrary 1129 number of attributes, each with a unique name. 1130 1131 @note The attributes are not XMLNodes. You may only query the 1132 Next() attribute in a list. 1133 */ 1134 class TINYXML2_LIB XMLAttribute 1135 { 1136 friend class XMLElement; 1137 public: 1138 /// The name of the attribute. 1139 const char* Name() const; 1140 1141 /// The value of the attribute. 1142 const char* Value() const; 1143 1144 /// Gets the line number the attribute is in, if the document was parsed from a file. 1145 int GetLineNum() const { return _parseLineNum; } 1146 1147 /// The next attribute in the list. 1148 const XMLAttribute* Next() const { 1149 return _next; 1150 } 1151 1152 /** IntValue interprets the attribute as an integer, and returns the value. 1153 If the value isn't an integer, 0 will be returned. There is no error checking; 1154 use QueryIntValue() if you need error checking. 1155 */ 1156 int IntValue() const { 1157 int i = 0; 1158 QueryIntValue(&i); 1159 return i; 1160 } 1161 1162 int64_t Int64Value() const { 1163 int64_t i = 0; 1164 QueryInt64Value(&i); 1165 return i; 1166 } 1167 1168 uint64_t Unsigned64Value() const { 1169 uint64_t i = 0; 1170 QueryUnsigned64Value(&i); 1171 return i; 1172 } 1173 1174 /// Query as an unsigned integer. See IntValue() 1175 unsigned UnsignedValue() const { 1176 unsigned i=0; 1177 QueryUnsignedValue( &i ); 1178 return i; 1179 } 1180 /// Query as a boolean. See IntValue() 1181 bool BoolValue() const { 1182 bool b=false; 1183 QueryBoolValue( &b ); 1184 return b; 1185 } 1186 /// Query as a double. See IntValue() 1187 double DoubleValue() const { 1188 double d=0; 1189 QueryDoubleValue( &d ); 1190 return d; 1191 } 1192 /// Query as a float. See IntValue() 1193 float FloatValue() const { 1194 float f=0; 1195 QueryFloatValue( &f ); 1196 return f; 1197 } 1198 1199 /** QueryIntValue interprets the attribute as an integer, and returns the value 1200 in the provided parameter. The function will return XML_SUCCESS on success, 1201 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. 1202 */ 1203 XMLError QueryIntValue( int* value ) const; 1204 /// See QueryIntValue 1205 XMLError QueryUnsignedValue( unsigned int* value ) const; 1206 /// See QueryIntValue 1207 XMLError QueryInt64Value(int64_t* value) const; 1208 /// See QueryIntValue 1209 XMLError QueryUnsigned64Value(uint64_t* value) const; 1210 /// See QueryIntValue 1211 XMLError QueryBoolValue( bool* value ) const; 1212 /// See QueryIntValue 1213 XMLError QueryDoubleValue( double* value ) const; 1214 /// See QueryIntValue 1215 XMLError QueryFloatValue( float* value ) const; 1216 1217 /// Set the attribute to a string value. 1218 void SetAttribute( const char* value ); 1219 /// Set the attribute to value. 1220 void SetAttribute( int value ); 1221 /// Set the attribute to value. 1222 void SetAttribute( unsigned value ); 1223 /// Set the attribute to value. 1224 void SetAttribute(int64_t value); 1225 /// Set the attribute to value. 1226 void SetAttribute(uint64_t value); 1227 /// Set the attribute to value. 1228 void SetAttribute( bool value ); 1229 /// Set the attribute to value. 1230 void SetAttribute( double value ); 1231 /// Set the attribute to value. 1232 void SetAttribute( float value ); 1233 1234 private: 1235 enum { BUF_SIZE = 200 }; 1236 1237 XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} 1238 virtual ~XMLAttribute() {} 1239 1240 XMLAttribute( const XMLAttribute& ); // not supported 1241 void operator=( const XMLAttribute& ); // not supported 1242 void SetName( const char* name ); 1243 1244 char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr ); 1245 1246 mutable StrPair _name; 1247 mutable StrPair _value; 1248 int _parseLineNum; 1249 XMLAttribute* _next; 1250 MemPool* _memPool; 1251 }; 1252 1253 1254 /** The element is a container class. It has a value, the element name, 1255 and can contain other elements, text, comments, and unknowns. 1256 Elements also contain an arbitrary number of attributes. 1257 */ 1258 class TINYXML2_LIB XMLElement : public XMLNode 1259 { 1260 friend class XMLDocument; 1261 public: 1262 /// Get the name of an element (which is the Value() of the node.) 1263 const char* Name() const { 1264 return Value(); 1265 } 1266 /// Set the name of the element. 1267 void SetName( const char* str, bool staticMem=false ) { 1268 SetValue( str, staticMem ); 1269 } 1270 1271 virtual XMLElement* ToElement() { 1272 return this; 1273 } 1274 virtual const XMLElement* ToElement() const { 1275 return this; 1276 } 1277 virtual bool Accept( XMLVisitor* visitor ) const; 1278 1279 /** Given an attribute name, Attribute() returns the value 1280 for the attribute of that name, or null if none 1281 exists. For example: 1282 1283 @verbatim 1284 const char* value = ele->Attribute( "foo" ); 1285 @endverbatim 1286 1287 The 'value' parameter is normally null. However, if specified, 1288 the attribute will only be returned if the 'name' and 'value' 1289 match. This allow you to write code: 1290 1291 @verbatim 1292 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); 1293 @endverbatim 1294 1295 rather than: 1296 @verbatim 1297 if ( ele->Attribute( "foo" ) ) { 1298 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); 1299 } 1300 @endverbatim 1301 */ 1302 const char* Attribute( const char* name, const char* value=0 ) const; 1303 1304 /** Given an attribute name, IntAttribute() returns the value 1305 of the attribute interpreted as an integer. The default 1306 value will be returned if the attribute isn't present, 1307 or if there is an error. (For a method with error 1308 checking, see QueryIntAttribute()). 1309 */ 1310 int IntAttribute(const char* name, int defaultValue = 0) const; 1311 /// See IntAttribute() 1312 unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const; 1313 /// See IntAttribute() 1314 int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const; 1315 /// See IntAttribute() 1316 uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const; 1317 /// See IntAttribute() 1318 bool BoolAttribute(const char* name, bool defaultValue = false) const; 1319 /// See IntAttribute() 1320 double DoubleAttribute(const char* name, double defaultValue = 0) const; 1321 /// See IntAttribute() 1322 float FloatAttribute(const char* name, float defaultValue = 0) const; 1323 1324 /** Given an attribute name, QueryIntAttribute() returns 1325 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion 1326 can't be performed, or XML_NO_ATTRIBUTE if the attribute 1327 doesn't exist. If successful, the result of the conversion 1328 will be written to 'value'. If not successful, nothing will 1329 be written to 'value'. This allows you to provide default 1330 value: 1331 1332 @verbatim 1333 int value = 10; 1334 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 1335 @endverbatim 1336 */ 1337 XMLError QueryIntAttribute( const char* name, int* value ) const { 1338 const XMLAttribute* a = FindAttribute( name ); 1339 if ( !a ) { 1340 return XML_NO_ATTRIBUTE; 1341 } 1342 return a->QueryIntValue( value ); 1343 } 1344 1345 /// See QueryIntAttribute() 1346 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { 1347 const XMLAttribute* a = FindAttribute( name ); 1348 if ( !a ) { 1349 return XML_NO_ATTRIBUTE; 1350 } 1351 return a->QueryUnsignedValue( value ); 1352 } 1353 1354 /// See QueryIntAttribute() 1355 XMLError QueryInt64Attribute(const char* name, int64_t* value) const { 1356 const XMLAttribute* a = FindAttribute(name); 1357 if (!a) { 1358 return XML_NO_ATTRIBUTE; 1359 } 1360 return a->QueryInt64Value(value); 1361 } 1362 1363 /// See QueryIntAttribute() 1364 XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const { 1365 const XMLAttribute* a = FindAttribute(name); 1366 if(!a) { 1367 return XML_NO_ATTRIBUTE; 1368 } 1369 return a->QueryUnsigned64Value(value); 1370 } 1371 1372 /// See QueryIntAttribute() 1373 XMLError QueryBoolAttribute( const char* name, bool* value ) const { 1374 const XMLAttribute* a = FindAttribute( name ); 1375 if ( !a ) { 1376 return XML_NO_ATTRIBUTE; 1377 } 1378 return a->QueryBoolValue( value ); 1379 } 1380 /// See QueryIntAttribute() 1381 XMLError QueryDoubleAttribute( const char* name, double* value ) const { 1382 const XMLAttribute* a = FindAttribute( name ); 1383 if ( !a ) { 1384 return XML_NO_ATTRIBUTE; 1385 } 1386 return a->QueryDoubleValue( value ); 1387 } 1388 /// See QueryIntAttribute() 1389 XMLError QueryFloatAttribute( const char* name, float* value ) const { 1390 const XMLAttribute* a = FindAttribute( name ); 1391 if ( !a ) { 1392 return XML_NO_ATTRIBUTE; 1393 } 1394 return a->QueryFloatValue( value ); 1395 } 1396 1397 /// See QueryIntAttribute() 1398 XMLError QueryStringAttribute(const char* name, const char** value) const { 1399 const XMLAttribute* a = FindAttribute(name); 1400 if (!a) { 1401 return XML_NO_ATTRIBUTE; 1402 } 1403 *value = a->Value(); 1404 return XML_SUCCESS; 1405 } 1406 1407 1408 1409 /** Given an attribute name, QueryAttribute() returns 1410 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion 1411 can't be performed, or XML_NO_ATTRIBUTE if the attribute 1412 doesn't exist. It is overloaded for the primitive types, 1413 and is a generally more convenient replacement of 1414 QueryIntAttribute() and related functions. 1415 1416 If successful, the result of the conversion 1417 will be written to 'value'. If not successful, nothing will 1418 be written to 'value'. This allows you to provide default 1419 value: 1420 1421 @verbatim 1422 int value = 10; 1423 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 1424 @endverbatim 1425 */ 1426 XMLError QueryAttribute( const char* name, int* value ) const { 1427 return QueryIntAttribute( name, value ); 1428 } 1429 1430 XMLError QueryAttribute( const char* name, unsigned int* value ) const { 1431 return QueryUnsignedAttribute( name, value ); 1432 } 1433 1434 XMLError QueryAttribute(const char* name, int64_t* value) const { 1435 return QueryInt64Attribute(name, value); 1436 } 1437 1438 XMLError QueryAttribute(const char* name, uint64_t* value) const { 1439 return QueryUnsigned64Attribute(name, value); 1440 } 1441 1442 XMLError QueryAttribute( const char* name, bool* value ) const { 1443 return QueryBoolAttribute( name, value ); 1444 } 1445 1446 XMLError QueryAttribute( const char* name, double* value ) const { 1447 return QueryDoubleAttribute( name, value ); 1448 } 1449 1450 XMLError QueryAttribute( const char* name, float* value ) const { 1451 return QueryFloatAttribute( name, value ); 1452 } 1453 1454 /// Sets the named attribute to value. 1455 void SetAttribute( const char* name, const char* value ) { 1456 XMLAttribute* a = FindOrCreateAttribute( name ); 1457 a->SetAttribute( value ); 1458 } 1459 /// Sets the named attribute to value. 1460 void SetAttribute( const char* name, int value ) { 1461 XMLAttribute* a = FindOrCreateAttribute( name ); 1462 a->SetAttribute( value ); 1463 } 1464 /// Sets the named attribute to value. 1465 void SetAttribute( const char* name, unsigned value ) { 1466 XMLAttribute* a = FindOrCreateAttribute( name ); 1467 a->SetAttribute( value ); 1468 } 1469 1470 /// Sets the named attribute to value. 1471 void SetAttribute(const char* name, int64_t value) { 1472 XMLAttribute* a = FindOrCreateAttribute(name); 1473 a->SetAttribute(value); 1474 } 1475 1476 /// Sets the named attribute to value. 1477 void SetAttribute(const char* name, uint64_t value) { 1478 XMLAttribute* a = FindOrCreateAttribute(name); 1479 a->SetAttribute(value); 1480 } 1481 1482 /// Sets the named attribute to value. 1483 void SetAttribute( const char* name, bool value ) { 1484 XMLAttribute* a = FindOrCreateAttribute( name ); 1485 a->SetAttribute( value ); 1486 } 1487 /// Sets the named attribute to value. 1488 void SetAttribute( const char* name, double value ) { 1489 XMLAttribute* a = FindOrCreateAttribute( name ); 1490 a->SetAttribute( value ); 1491 } 1492 /// Sets the named attribute to value. 1493 void SetAttribute( const char* name, float value ) { 1494 XMLAttribute* a = FindOrCreateAttribute( name ); 1495 a->SetAttribute( value ); 1496 } 1497 1498 /** 1499 Delete an attribute. 1500 */ 1501 void DeleteAttribute( const char* name ); 1502 1503 /// Return the first attribute in the list. 1504 const XMLAttribute* FirstAttribute() const { 1505 return _rootAttribute; 1506 } 1507 /// Query a specific attribute in the list. 1508 const XMLAttribute* FindAttribute( const char* name ) const; 1509 1510 /** Convenience function for easy access to the text inside an element. Although easy 1511 and concise, GetText() is limited compared to getting the XMLText child 1512 and accessing it directly. 1513 1514 If the first child of 'this' is a XMLText, the GetText() 1515 returns the character string of the Text node, else null is returned. 1516 1517 This is a convenient method for getting the text of simple contained text: 1518 @verbatim 1519 <foo>This is text</foo> 1520 const char* str = fooElement->GetText(); 1521 @endverbatim 1522 1523 'str' will be a pointer to "This is text". 1524 1525 Note that this function can be misleading. If the element foo was created from 1526 this XML: 1527 @verbatim 1528 <foo><b>This is text</b></foo> 1529 @endverbatim 1530 1531 then the value of str would be null. The first child node isn't a text node, it is 1532 another element. From this XML: 1533 @verbatim 1534 <foo>This is <b>text</b></foo> 1535 @endverbatim 1536 GetText() will return "This is ". 1537 */ 1538 const char* GetText() const; 1539 1540 /** Convenience function for easy access to the text inside an element. Although easy 1541 and concise, SetText() is limited compared to creating an XMLText child 1542 and mutating it directly. 1543 1544 If the first child of 'this' is a XMLText, SetText() sets its value to 1545 the given string, otherwise it will create a first child that is an XMLText. 1546 1547 This is a convenient method for setting the text of simple contained text: 1548 @verbatim 1549 <foo>This is text</foo> 1550 fooElement->SetText( "Hullaballoo!" ); 1551 <foo>Hullaballoo!</foo> 1552 @endverbatim 1553 1554 Note that this function can be misleading. If the element foo was created from 1555 this XML: 1556 @verbatim 1557 <foo><b>This is text</b></foo> 1558 @endverbatim 1559 1560 then it will not change "This is text", but rather prefix it with a text element: 1561 @verbatim 1562 <foo>Hullaballoo!<b>This is text</b></foo> 1563 @endverbatim 1564 1565 For this XML: 1566 @verbatim 1567 <foo /> 1568 @endverbatim 1569 SetText() will generate 1570 @verbatim 1571 <foo>Hullaballoo!</foo> 1572 @endverbatim 1573 */ 1574 void SetText( const char* inText ); 1575 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1576 void SetText( int value ); 1577 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1578 void SetText( unsigned value ); 1579 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1580 void SetText(int64_t value); 1581 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1582 void SetText(uint64_t value); 1583 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1584 void SetText( bool value ); 1585 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1586 void SetText( double value ); 1587 /// Convenience method for setting text inside an element. See SetText() for important limitations. 1588 void SetText( float value ); 1589 1590 /** 1591 Convenience method to query the value of a child text node. This is probably best 1592 shown by example. Given you have a document is this form: 1593 @verbatim 1594 <point> 1595 <x>1</x> 1596 <y>1.4</y> 1597 </point> 1598 @endverbatim 1599 1600 The QueryIntText() and similar functions provide a safe and easier way to get to the 1601 "value" of x and y. 1602 1603 @verbatim 1604 int x = 0; 1605 float y = 0; // types of x and y are contrived for example 1606 const XMLElement* xElement = pointElement->FirstChildElement( "x" ); 1607 const XMLElement* yElement = pointElement->FirstChildElement( "y" ); 1608 xElement->QueryIntText( &x ); 1609 yElement->QueryFloatText( &y ); 1610 @endverbatim 1611 1612 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted 1613 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. 1614 1615 */ 1616 XMLError QueryIntText( int* ival ) const; 1617 /// See QueryIntText() 1618 XMLError QueryUnsignedText( unsigned* uval ) const; 1619 /// See QueryIntText() 1620 XMLError QueryInt64Text(int64_t* uval) const; 1621 /// See QueryIntText() 1622 XMLError QueryUnsigned64Text(uint64_t* uval) const; 1623 /// See QueryIntText() 1624 XMLError QueryBoolText( bool* bval ) const; 1625 /// See QueryIntText() 1626 XMLError QueryDoubleText( double* dval ) const; 1627 /// See QueryIntText() 1628 XMLError QueryFloatText( float* fval ) const; 1629 1630 int IntText(int defaultValue = 0) const; 1631 1632 /// See QueryIntText() 1633 unsigned UnsignedText(unsigned defaultValue = 0) const; 1634 /// See QueryIntText() 1635 int64_t Int64Text(int64_t defaultValue = 0) const; 1636 /// See QueryIntText() 1637 uint64_t Unsigned64Text(uint64_t defaultValue = 0) const; 1638 /// See QueryIntText() 1639 bool BoolText(bool defaultValue = false) const; 1640 /// See QueryIntText() 1641 double DoubleText(double defaultValue = 0) const; 1642 /// See QueryIntText() 1643 float FloatText(float defaultValue = 0) const; 1644 1645 /** 1646 Convenience method to create a new XMLElement and add it as last (right) 1647 child of this node. Returns the created and inserted element. 1648 */ 1649 XMLElement* InsertNewChildElement(const char* name); 1650 /// See InsertNewChildElement() 1651 XMLComment* InsertNewComment(const char* comment); 1652 /// See InsertNewChildElement() 1653 XMLText* InsertNewText(const char* text); 1654 /// See InsertNewChildElement() 1655 XMLDeclaration* InsertNewDeclaration(const char* text); 1656 /// See InsertNewChildElement() 1657 XMLUnknown* InsertNewUnknown(const char* text); 1658 1659 1660 // internal: 1661 enum ElementClosingType { 1662 OPEN, // <foo> 1663 CLOSED, // <foo/> 1664 CLOSING // </foo> 1665 }; 1666 ElementClosingType ClosingType() const { 1667 return _closingType; 1668 } 1669 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1670 virtual bool ShallowEqual( const XMLNode* compare ) const; 1671 1672 protected: 1673 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); 1674 1675 private: 1676 XMLElement( XMLDocument* doc ); 1677 virtual ~XMLElement(); 1678 XMLElement( const XMLElement& ); // not supported 1679 void operator=( const XMLElement& ); // not supported 1680 1681 XMLAttribute* FindOrCreateAttribute( const char* name ); 1682 char* ParseAttributes( char* p, int* curLineNumPtr ); 1683 static void DeleteAttribute( XMLAttribute* attribute ); 1684 XMLAttribute* CreateAttribute(); 1685 1686 enum { BUF_SIZE = 200 }; 1687 ElementClosingType _closingType; 1688 // The attribute list is ordered; there is no 'lastAttribute' 1689 // because the list needs to be scanned for dupes before adding 1690 // a new attribute. 1691 XMLAttribute* _rootAttribute; 1692 }; 1693 1694 1695 enum Whitespace { 1696 PRESERVE_WHITESPACE, 1697 COLLAPSE_WHITESPACE 1698 }; 1699 1700 1701 /** A Document binds together all the functionality. 1702 It can be saved, loaded, and printed to the screen. 1703 All Nodes are connected and allocated to a Document. 1704 If the Document is deleted, all its Nodes are also deleted. 1705 */ 1706 class TINYXML2_LIB XMLDocument : public XMLNode 1707 { 1708 friend class XMLElement; 1709 // Gives access to SetError and Push/PopDepth, but over-access for everything else. 1710 // Wishing C++ had "internal" scope. 1711 friend class XMLNode; 1712 friend class XMLText; 1713 friend class XMLComment; 1714 friend class XMLDeclaration; 1715 friend class XMLUnknown; 1716 public: 1717 /// constructor 1718 XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); 1719 ~XMLDocument(); 1720 1721 virtual XMLDocument* ToDocument() { 1722 TIXMLASSERT( this == _document ); 1723 return this; 1724 } 1725 virtual const XMLDocument* ToDocument() const { 1726 TIXMLASSERT( this == _document ); 1727 return this; 1728 } 1729 1730 /** 1731 Parse an XML file from a character string. 1732 Returns XML_SUCCESS (0) on success, or 1733 an errorID. 1734 1735 You may optionally pass in the 'nBytes', which is 1736 the number of bytes which will be parsed. If not 1737 specified, TinyXML-2 will assume 'xml' points to a 1738 null terminated string. 1739 */ 1740 XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) ); 1741 1742 /** 1743 Load an XML file from disk. 1744 Returns XML_SUCCESS (0) on success, or 1745 an errorID. 1746 */ 1747 XMLError LoadFile( const char* filename ); 1748 1749 /** 1750 Load an XML file from disk. You are responsible 1751 for providing and closing the FILE*. 1752 1753 NOTE: The file should be opened as binary ("rb") 1754 not text in order for TinyXML-2 to correctly 1755 do newline normalization. 1756 1757 Returns XML_SUCCESS (0) on success, or 1758 an errorID. 1759 */ 1760 XMLError LoadFile( FILE* ); 1761 1762 /** 1763 Save the XML file to disk. 1764 Returns XML_SUCCESS (0) on success, or 1765 an errorID. 1766 */ 1767 XMLError SaveFile( const char* filename, bool compact = false ); 1768 1769 /** 1770 Save the XML file to disk. You are responsible 1771 for providing and closing the FILE*. 1772 1773 Returns XML_SUCCESS (0) on success, or 1774 an errorID. 1775 */ 1776 XMLError SaveFile( FILE* fp, bool compact = false ); 1777 1778 bool ProcessEntities() const { 1779 return _processEntities; 1780 } 1781 Whitespace WhitespaceMode() const { 1782 return _whitespaceMode; 1783 } 1784 1785 /** 1786 Returns true if this document has a leading Byte Order Mark of UTF8. 1787 */ 1788 bool HasBOM() const { 1789 return _writeBOM; 1790 } 1791 /** Sets whether to write the BOM when writing the file. 1792 */ 1793 void SetBOM( bool useBOM ) { 1794 _writeBOM = useBOM; 1795 } 1796 1797 /** Return the root element of DOM. Equivalent to FirstChildElement(). 1798 To get the first node, use FirstChild(). 1799 */ 1800 XMLElement* RootElement() { 1801 return FirstChildElement(); 1802 } 1803 const XMLElement* RootElement() const { 1804 return FirstChildElement(); 1805 } 1806 1807 /** Print the Document. If the Printer is not provided, it will 1808 print to stdout. If you provide Printer, this can print to a file: 1809 @verbatim 1810 XMLPrinter printer( fp ); 1811 doc.Print( &printer ); 1812 @endverbatim 1813 1814 Or you can use a printer to print to memory: 1815 @verbatim 1816 XMLPrinter printer; 1817 doc.Print( &printer ); 1818 // printer.CStr() has a const char* to the XML 1819 @endverbatim 1820 */ 1821 void Print( XMLPrinter* streamer=0 ) const; 1822 virtual bool Accept( XMLVisitor* visitor ) const; 1823 1824 /** 1825 Create a new Element associated with 1826 this Document. The memory for the Element 1827 is managed by the Document. 1828 */ 1829 XMLElement* NewElement( const char* name ); 1830 /** 1831 Create a new Comment associated with 1832 this Document. The memory for the Comment 1833 is managed by the Document. 1834 */ 1835 XMLComment* NewComment( const char* comment ); 1836 /** 1837 Create a new Text associated with 1838 this Document. The memory for the Text 1839 is managed by the Document. 1840 */ 1841 XMLText* NewText( const char* text ); 1842 /** 1843 Create a new Declaration associated with 1844 this Document. The memory for the object 1845 is managed by the Document. 1846 1847 If the 'text' param is null, the standard 1848 declaration is used.: 1849 @verbatim 1850 <?xml version="1.0" encoding="UTF-8"?> 1851 @endverbatim 1852 */ 1853 XMLDeclaration* NewDeclaration( const char* text=0 ); 1854 /** 1855 Create a new Unknown associated with 1856 this Document. The memory for the object 1857 is managed by the Document. 1858 */ 1859 XMLUnknown* NewUnknown( const char* text ); 1860 1861 /** 1862 Delete a node associated with this document. 1863 It will be unlinked from the DOM. 1864 */ 1865 void DeleteNode( XMLNode* node ); 1866 1867 void ClearError() { 1868 SetError(XML_SUCCESS, 0, 0); 1869 } 1870 1871 /// Return true if there was an error parsing the document. 1872 bool Error() const { 1873 return _errorID != XML_SUCCESS; 1874 } 1875 /// Return the errorID. 1876 XMLError ErrorID() const { 1877 return _errorID; 1878 } 1879 const char* ErrorName() const; 1880 static const char* ErrorIDToName(XMLError errorID); 1881 1882 /** Returns a "long form" error description. A hopefully helpful 1883 diagnostic with location, line number, and/or additional info. 1884 */ 1885 const char* ErrorStr() const; 1886 1887 /// A (trivial) utility function that prints the ErrorStr() to stdout. 1888 void PrintError() const; 1889 1890 /// Return the line where the error occurred, or zero if unknown. 1891 int ErrorLineNum() const 1892 { 1893 return _errorLineNum; 1894 } 1895 1896 /// Clear the document, resetting it to the initial state. 1897 void Clear(); 1898 1899 /** 1900 Copies this document to a target document. 1901 The target will be completely cleared before the copy. 1902 If you want to copy a sub-tree, see XMLNode::DeepClone(). 1903 1904 NOTE: that the 'target' must be non-null. 1905 */ 1906 void DeepCopy(XMLDocument* target) const; 1907 1908 // internal 1909 char* Identify( char* p, XMLNode** node ); 1910 1911 // internal 1912 void MarkInUse(const XMLNode* const); 1913 1914 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { 1915 return 0; 1916 } 1917 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { 1918 return false; 1919 } 1920 1921 private: 1922 XMLDocument( const XMLDocument& ); // not supported 1923 void operator=( const XMLDocument& ); // not supported 1924 1925 bool _writeBOM; 1926 bool _processEntities; 1927 XMLError _errorID; 1928 Whitespace _whitespaceMode; 1929 mutable StrPair _errorStr; 1930 int _errorLineNum; 1931 char* _charBuffer; 1932 int _parseCurLineNum; 1933 int _parsingDepth; 1934 // Memory tracking does add some overhead. 1935 // However, the code assumes that you don't 1936 // have a bunch of unlinked nodes around. 1937 // Therefore it takes less memory to track 1938 // in the document vs. a linked list in the XMLNode, 1939 // and the performance is the same. 1940 DynArray<XMLNode*, 10> _unlinked; 1941 1942 MemPoolT< sizeof(XMLElement) > _elementPool; 1943 MemPoolT< sizeof(XMLAttribute) > _attributePool; 1944 MemPoolT< sizeof(XMLText) > _textPool; 1945 MemPoolT< sizeof(XMLComment) > _commentPool; 1946 1947 static const char* _errorNames[XML_ERROR_COUNT]; 1948 1949 void Parse(); 1950 1951 void SetError( XMLError error, int lineNum, const char* format, ... ); 1952 1953 // Something of an obvious security hole, once it was discovered. 1954 // Either an ill-formed XML or an excessively deep one can overflow 1955 // the stack. Track stack depth, and error out if needed. 1956 class DepthTracker { 1957 public: 1958 explicit DepthTracker(XMLDocument * document) { 1959 this->_document = document; 1960 document->PushDepth(); 1961 } 1962 ~DepthTracker() { 1963 _document->PopDepth(); 1964 } 1965 private: 1966 XMLDocument * _document; 1967 }; 1968 void PushDepth(); 1969 void PopDepth(); 1970 1971 template<class NodeType, int PoolElementSize> 1972 NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool ); 1973 }; 1974 1975 template<class NodeType, int PoolElementSize> 1976 inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool ) 1977 { 1978 TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); 1979 TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); 1980 NodeType* returnNode = new (pool.Alloc()) NodeType( this ); 1981 TIXMLASSERT( returnNode ); 1982 returnNode->_memPool = &pool; 1983 1984 _unlinked.Push(returnNode); 1985 return returnNode; 1986 } 1987 1988 /** 1989 A XMLHandle is a class that wraps a node pointer with null checks; this is 1990 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 1991 DOM structure. It is a separate utility class. 1992 1993 Take an example: 1994 @verbatim 1995 <Document> 1996 <Element attributeA = "valueA"> 1997 <Child attributeB = "value1" /> 1998 <Child attributeB = "value2" /> 1999 </Element> 2000 </Document> 2001 @endverbatim 2002 2003 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 2004 easy to write a *lot* of code that looks like: 2005 2006 @verbatim 2007 XMLElement* root = document.FirstChildElement( "Document" ); 2008 if ( root ) 2009 { 2010 XMLElement* element = root->FirstChildElement( "Element" ); 2011 if ( element ) 2012 { 2013 XMLElement* child = element->FirstChildElement( "Child" ); 2014 if ( child ) 2015 { 2016 XMLElement* child2 = child->NextSiblingElement( "Child" ); 2017 if ( child2 ) 2018 { 2019 // Finally do something useful. 2020 @endverbatim 2021 2022 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity 2023 of such code. A XMLHandle checks for null pointers so it is perfectly safe 2024 and correct to use: 2025 2026 @verbatim 2027 XMLHandle docHandle( &document ); 2028 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); 2029 if ( child2 ) 2030 { 2031 // do something useful 2032 @endverbatim 2033 2034 Which is MUCH more concise and useful. 2035 2036 It is also safe to copy handles - internally they are nothing more than node pointers. 2037 @verbatim 2038 XMLHandle handleCopy = handle; 2039 @endverbatim 2040 2041 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. 2042 */ 2043 class TINYXML2_LIB XMLHandle 2044 { 2045 public: 2046 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. 2047 explicit XMLHandle( XMLNode* node ) : _node( node ) { 2048 } 2049 /// Create a handle from a node. 2050 explicit XMLHandle( XMLNode& node ) : _node( &node ) { 2051 } 2052 /// Copy constructor 2053 XMLHandle( const XMLHandle& ref ) : _node( ref._node ) { 2054 } 2055 /// Assignment 2056 XMLHandle& operator=( const XMLHandle& ref ) { 2057 _node = ref._node; 2058 return *this; 2059 } 2060 2061 /// Get the first child of this handle. 2062 XMLHandle FirstChild() { 2063 return XMLHandle( _node ? _node->FirstChild() : 0 ); 2064 } 2065 /// Get the first child element of this handle. 2066 XMLHandle FirstChildElement( const char* name = 0 ) { 2067 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); 2068 } 2069 /// Get the last child of this handle. 2070 XMLHandle LastChild() { 2071 return XMLHandle( _node ? _node->LastChild() : 0 ); 2072 } 2073 /// Get the last child element of this handle. 2074 XMLHandle LastChildElement( const char* name = 0 ) { 2075 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); 2076 } 2077 /// Get the previous sibling of this handle. 2078 XMLHandle PreviousSibling() { 2079 return XMLHandle( _node ? _node->PreviousSibling() : 0 ); 2080 } 2081 /// Get the previous sibling element of this handle. 2082 XMLHandle PreviousSiblingElement( const char* name = 0 ) { 2083 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); 2084 } 2085 /// Get the next sibling of this handle. 2086 XMLHandle NextSibling() { 2087 return XMLHandle( _node ? _node->NextSibling() : 0 ); 2088 } 2089 /// Get the next sibling element of this handle. 2090 XMLHandle NextSiblingElement( const char* name = 0 ) { 2091 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); 2092 } 2093 2094 /// Safe cast to XMLNode. This can return null. 2095 XMLNode* ToNode() { 2096 return _node; 2097 } 2098 /// Safe cast to XMLElement. This can return null. 2099 XMLElement* ToElement() { 2100 return ( _node ? _node->ToElement() : 0 ); 2101 } 2102 /// Safe cast to XMLText. This can return null. 2103 XMLText* ToText() { 2104 return ( _node ? _node->ToText() : 0 ); 2105 } 2106 /// Safe cast to XMLUnknown. This can return null. 2107 XMLUnknown* ToUnknown() { 2108 return ( _node ? _node->ToUnknown() : 0 ); 2109 } 2110 /// Safe cast to XMLDeclaration. This can return null. 2111 XMLDeclaration* ToDeclaration() { 2112 return ( _node ? _node->ToDeclaration() : 0 ); 2113 } 2114 2115 private: 2116 XMLNode* _node; 2117 }; 2118 2119 2120 /** 2121 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the 2122 same in all regards, except for the 'const' qualifiers. See XMLHandle for API. 2123 */ 2124 class TINYXML2_LIB XMLConstHandle 2125 { 2126 public: 2127 explicit XMLConstHandle( const XMLNode* node ) : _node( node ) { 2128 } 2129 explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) { 2130 } 2131 XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) { 2132 } 2133 2134 XMLConstHandle& operator=( const XMLConstHandle& ref ) { 2135 _node = ref._node; 2136 return *this; 2137 } 2138 2139 const XMLConstHandle FirstChild() const { 2140 return XMLConstHandle( _node ? _node->FirstChild() : 0 ); 2141 } 2142 const XMLConstHandle FirstChildElement( const char* name = 0 ) const { 2143 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); 2144 } 2145 const XMLConstHandle LastChild() const { 2146 return XMLConstHandle( _node ? _node->LastChild() : 0 ); 2147 } 2148 const XMLConstHandle LastChildElement( const char* name = 0 ) const { 2149 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); 2150 } 2151 const XMLConstHandle PreviousSibling() const { 2152 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); 2153 } 2154 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { 2155 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); 2156 } 2157 const XMLConstHandle NextSibling() const { 2158 return XMLConstHandle( _node ? _node->NextSibling() : 0 ); 2159 } 2160 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { 2161 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); 2162 } 2163 2164 2165 const XMLNode* ToNode() const { 2166 return _node; 2167 } 2168 const XMLElement* ToElement() const { 2169 return ( _node ? _node->ToElement() : 0 ); 2170 } 2171 const XMLText* ToText() const { 2172 return ( _node ? _node->ToText() : 0 ); 2173 } 2174 const XMLUnknown* ToUnknown() const { 2175 return ( _node ? _node->ToUnknown() : 0 ); 2176 } 2177 const XMLDeclaration* ToDeclaration() const { 2178 return ( _node ? _node->ToDeclaration() : 0 ); 2179 } 2180 2181 private: 2182 const XMLNode* _node; 2183 }; 2184 2185 2186 /** 2187 Printing functionality. The XMLPrinter gives you more 2188 options than the XMLDocument::Print() method. 2189 2190 It can: 2191 -# Print to memory. 2192 -# Print to a file you provide. 2193 -# Print XML without a XMLDocument. 2194 2195 Print to Memory 2196 2197 @verbatim 2198 XMLPrinter printer; 2199 doc.Print( &printer ); 2200 SomeFunction( printer.CStr() ); 2201 @endverbatim 2202 2203 Print to a File 2204 2205 You provide the file pointer. 2206 @verbatim 2207 XMLPrinter printer( fp ); 2208 doc.Print( &printer ); 2209 @endverbatim 2210 2211 Print without a XMLDocument 2212 2213 When loading, an XML parser is very useful. However, sometimes 2214 when saving, it just gets in the way. The code is often set up 2215 for streaming, and constructing the DOM is just overhead. 2216 2217 The Printer supports the streaming case. The following code 2218 prints out a trivially simple XML file without ever creating 2219 an XML document. 2220 2221 @verbatim 2222 XMLPrinter printer( fp ); 2223 printer.OpenElement( "foo" ); 2224 printer.PushAttribute( "foo", "bar" ); 2225 printer.CloseElement(); 2226 @endverbatim 2227 */ 2228 class TINYXML2_LIB XMLPrinter : public XMLVisitor 2229 { 2230 public: 2231 /** Construct the printer. If the FILE* is specified, 2232 this will print to the FILE. Else it will print 2233 to memory, and the result is available in CStr(). 2234 If 'compact' is set to true, then output is created 2235 with only required whitespace and newlines. 2236 */ 2237 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); 2238 virtual ~XMLPrinter() {} 2239 2240 /** If streaming, write the BOM and declaration. */ 2241 void PushHeader( bool writeBOM, bool writeDeclaration ); 2242 /** If streaming, start writing an element. 2243 The element must be closed with CloseElement() 2244 */ 2245 void OpenElement( const char* name, bool compactMode=false ); 2246 /// If streaming, add an attribute to an open element. 2247 void PushAttribute( const char* name, const char* value ); 2248 void PushAttribute( const char* name, int value ); 2249 void PushAttribute( const char* name, unsigned value ); 2250 void PushAttribute( const char* name, int64_t value ); 2251 void PushAttribute( const char* name, uint64_t value ); 2252 void PushAttribute( const char* name, bool value ); 2253 void PushAttribute( const char* name, double value ); 2254 /// If streaming, close the Element. 2255 virtual void CloseElement( bool compactMode=false ); 2256 2257 /// Add a text node. 2258 void PushText( const char* text, bool cdata=false ); 2259 /// Add a text node from an integer. 2260 void PushText( int value ); 2261 /// Add a text node from an unsigned. 2262 void PushText( unsigned value ); 2263 /// Add a text node from a signed 64bit integer. 2264 void PushText( int64_t value ); 2265 /// Add a text node from an unsigned 64bit integer. 2266 void PushText( uint64_t value ); 2267 /// Add a text node from a bool. 2268 void PushText( bool value ); 2269 /// Add a text node from a float. 2270 void PushText( float value ); 2271 /// Add a text node from a double. 2272 void PushText( double value ); 2273 2274 /// Add a comment 2275 void PushComment( const char* comment ); 2276 2277 void PushDeclaration( const char* value ); 2278 void PushUnknown( const char* value ); 2279 2280 virtual bool VisitEnter( const XMLDocument& /*doc*/ ); 2281 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { 2282 return true; 2283 } 2284 2285 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); 2286 virtual bool VisitExit( const XMLElement& element ); 2287 2288 virtual bool Visit( const XMLText& text ); 2289 virtual bool Visit( const XMLComment& comment ); 2290 virtual bool Visit( const XMLDeclaration& declaration ); 2291 virtual bool Visit( const XMLUnknown& unknown ); 2292 2293 /** 2294 If in print to memory mode, return a pointer to 2295 the XML file in memory. 2296 */ 2297 const char* CStr() const { 2298 return _buffer.Mem(); 2299 } 2300 /** 2301 If in print to memory mode, return the size 2302 of the XML file in memory. (Note the size returned 2303 includes the terminating null.) 2304 */ 2305 int CStrSize() const { 2306 return _buffer.Size(); 2307 } 2308 /** 2309 If in print to memory mode, reset the buffer to the 2310 beginning. 2311 */ 2312 void ClearBuffer( bool resetToFirstElement = true ) { 2313 _buffer.Clear(); 2314 _buffer.Push(0); 2315 _firstElement = resetToFirstElement; 2316 } 2317 2318 protected: 2319 virtual bool CompactMode( const XMLElement& ) { return _compactMode; } 2320 2321 /** Prints out the space before an element. You may override to change 2322 the space and tabs used. A PrintSpace() override should call Print(). 2323 */ 2324 virtual void PrintSpace( int depth ); 2325 void Print( const char* format, ... ); 2326 void Write( const char* data, size_t size ); 2327 inline void Write( const char* data ) { Write( data, strlen( data ) ); } 2328 void Putc( char ch ); 2329 2330 void SealElementIfJustOpened(); 2331 bool _elementJustOpened; 2332 DynArray< const char*, 10 > _stack; 2333 2334 private: 2335 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. 2336 2337 bool _firstElement; 2338 FILE* _fp; 2339 int _depth; 2340 int _textDepth; 2341 bool _processEntities; 2342 bool _compactMode; 2343 2344 enum { 2345 ENTITY_RANGE = 64, 2346 BUF_SIZE = 200 2347 }; 2348 bool _entityFlag[ENTITY_RANGE]; 2349 bool _restrictedEntityFlag[ENTITY_RANGE]; 2350 2351 DynArray< char, 20 > _buffer; 2352 2353 // Prohibit cloning, intentionally not implemented 2354 XMLPrinter( const XMLPrinter& ); 2355 XMLPrinter& operator=( const XMLPrinter& ); 2356 }; 2357 2358 2359 } // tinyxml2 2360 2361 #if defined(_MSC_VER) 2362 # pragma warning(pop) 2363 #endif 2364 2365 #endif // TINYXML2_INCLUDED