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