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