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