blob: 4e29a5f3ad7cf303970255ca14deb39f3d5c4ad3 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070027#ifdef ANDROID_NDK
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
48 g++ -Wall 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
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# 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 ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// 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);*/
85inline 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
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700103static const int TIXML2_PATCH_VERSION = 8;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
111class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800112class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800113class XMLDeclaration;
114class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800115
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118/*
119 A class that wraps strings. Normally stores the start and end
120 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800121 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800122 manage) a traditional char[]
123*/
Lee Thomason39ede242012-01-20 11:27:56 -0800124class StrPair
125{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700127 enum {
128 NEEDS_ENTITY_PROCESSING = 0x01,
129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700132 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 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700140 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 void Set( char* _start, char* _end, int _flags ) {
144 Reset();
145 this->start = _start;
146 this->end = _end;
147 this->flags = _flags | NEEDS_FLUSH;
148 }
149 const char* GetStr();
150 bool Empty() const {
151 return start == end;
152 }
Lee Thomason39ede242012-01-20 11:27:56 -0800153
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 void SetInternedStr( const char* str ) {
155 Reset();
156 this->start = const_cast<char*>(str);
157 }
158 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800159
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 char* ParseText( char* in, const char* endTag, int strFlags );
161 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800162
Lee Thomason2c85a712012-01-31 08:24:24 -0800163
Lee Thomason39ede242012-01-20 11:27:56 -0800164private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700165 void Reset();
166 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 enum {
169 NEEDS_FLUSH = 0x100,
170 NEEDS_DELETE = 0x200
171 };
Lee Thomasone4422302012-01-20 17:59:50 -0800172
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700173 // After parsing, if *end != 0, it can be set to zero.
174 int flags;
175 char* start;
176 char* end;
Lee Thomason39ede242012-01-20 11:27:56 -0800177};
178
U-Lama\Lee560bd472011-12-28 19:42:49 -0800179
U-Stream\Leeae25a442012-02-17 17:48:16 -0800180/*
181 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
182 Has a small initial memory pool, so that low or no usage will not
183 cause a call to new/delete
184*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800185template <class T, int INIT>
186class DynArray
187{
188public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700189 DynArray< T, INIT >() {
190 mem = pool;
191 allocated = INIT;
192 size = 0;
193 }
194 ~DynArray() {
195 if ( mem != pool ) {
196 delete [] mem;
197 }
198 }
199 void Push( T t ) {
200 EnsureCapacity( size+1 );
201 mem[size++] = t;
202 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800203
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700204 T* PushArr( int count ) {
205 EnsureCapacity( size+count );
206 T* ret = &mem[size];
207 size += count;
208 return ret;
209 }
210 T Pop() {
211 return mem[--size];
212 }
213 void PopArr( int count ) {
214 TIXMLASSERT( size >= count );
215 size -= count;
216 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800217
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700218 bool Empty() const {
219 return size == 0;
220 }
221 T& operator[](int i) {
222 TIXMLASSERT( i>= 0 && i < size );
223 return mem[i];
224 }
225 const T& operator[](int i) const {
226 TIXMLASSERT( i>= 0 && i < size );
227 return mem[i];
228 }
229 int Size() const {
230 return size;
231 }
232 int Capacity() const {
233 return allocated;
234 }
235 const T* Mem() const {
236 return mem;
237 }
238 T* Mem() {
239 return mem;
240 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800241
242
243private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 void EnsureCapacity( int cap ) {
245 if ( cap > allocated ) {
246 int newAllocated = cap * 2;
247 T* newMem = new T[newAllocated];
248 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
249 if ( mem != pool ) {
250 delete [] mem;
251 }
252 mem = newMem;
253 allocated = newAllocated;
254 }
255 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800256
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 T* mem;
258 T pool[INIT];
259 int allocated; // objects allocated
260 int size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800261};
262
Lee Thomason50adb4c2012-02-13 15:07:09 -0800263
U-Stream\Leeae25a442012-02-17 17:48:16 -0800264/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200265 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800266 and deallocation of objects.
267*/
Lee Thomasond1983222012-02-06 08:41:24 -0800268class MemPool
269{
270public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 MemPool() {}
272 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800273
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700274 virtual int ItemSize() const = 0;
275 virtual void* Alloc() = 0;
276 virtual void Free( void* ) = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800277};
278
Lee Thomason50adb4c2012-02-13 15:07:09 -0800279
U-Stream\Leeae25a442012-02-17 17:48:16 -0800280/*
281 Template child class to create pools of the correct type.
282*/
Lee Thomasond1983222012-02-06 08:41:24 -0800283template< int SIZE >
284class MemPoolT : public MemPool
285{
286public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700287 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
288 ~MemPoolT() {
289 // Delete the blocks.
290 for( int i=0; i<blockPtrs.Size(); ++i ) {
291 delete blockPtrs[i];
292 }
293 }
Lee Thomasond1983222012-02-06 08:41:24 -0800294
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700295 virtual int ItemSize() const {
296 return SIZE;
297 }
298 int CurrentAllocs() const {
299 return currentAllocs;
300 }
Lee Thomasond1983222012-02-06 08:41:24 -0800301
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700302 virtual void* Alloc() {
303 if ( !root ) {
304 // Need a new block.
305 Block* block = new Block();
306 blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800307
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700308 for( int i=0; i<COUNT-1; ++i ) {
309 block->chunk[i].next = &block->chunk[i+1];
310 }
311 block->chunk[COUNT-1].next = 0;
312 root = block->chunk;
313 }
314 void* result = root;
315 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800316
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700317 ++currentAllocs;
318 if ( currentAllocs > maxAllocs ) {
319 maxAllocs = currentAllocs;
320 }
321 nAllocs++;
322 return result;
323 }
324 virtual void Free( void* mem ) {
325 if ( !mem ) {
326 return;
327 }
328 --currentAllocs;
329 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700330#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700332#endif
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 chunk->next = root;
334 root = chunk;
335 }
336 void Trace( const char* name ) {
337 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
338 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
339 }
Lee Thomasond1983222012-02-06 08:41:24 -0800340
341private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 enum { COUNT = 1024/SIZE };
343 union Chunk {
344 Chunk* next;
345 char mem[SIZE];
346 };
347 struct Block {
348 Chunk chunk[COUNT];
349 };
350 DynArray< Block*, 10 > blockPtrs;
351 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800352
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 int currentAllocs;
354 int nAllocs;
355 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800356};
357
Lee Thomason2c85a712012-01-31 08:24:24 -0800358
Lee Thomason56bdd022012-02-09 18:16:58 -0800359
360/**
361 Implements the interface to the "Visitor pattern" (see the Accept() method.)
362 If you call the Accept() method, it requires being passed a XMLVisitor
363 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200364 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800365 are simply called with Visit().
366
367 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200368 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800369
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700370 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800371 visiting). You need to only override methods that are interesting to you.
372
Thomas Roß08bdf502012-05-12 14:21:23 +0200373 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800374
375 You should never change the document from a callback.
376
377 @sa XMLNode::Accept()
378*/
379class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800380{
381public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700382 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800383
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700384 /// Visit a document.
385 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
386 return true;
387 }
388 /// Visit a document.
389 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
390 return true;
391 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800392
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 /// Visit an element.
394 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
395 return true;
396 }
397 /// Visit an element.
398 virtual bool VisitExit( const XMLElement& /*element*/ ) {
399 return true;
400 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800401
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700402 /// Visit a declaration.
403 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
404 return true;
405 }
406 /// Visit a text node.
407 virtual bool Visit( const XMLText& /*text*/ ) {
408 return true;
409 }
410 /// Visit a comment node.
411 virtual bool Visit( const XMLComment& /*comment*/ ) {
412 return true;
413 }
414 /// Visit an unknown node.
415 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
416 return true;
417 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800418};
419
420
U-Stream\Leeae25a442012-02-17 17:48:16 -0800421/*
422 Utility functionality.
423*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800424class XMLUtil
425{
Lee Thomasond1983222012-02-06 08:41:24 -0800426public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700427 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
428 // correct, but simple, and usually works.
429 static const char* SkipWhiteSpace( const char* p ) {
430 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
431 ++p;
432 }
433 return p;
434 }
435 static char* SkipWhiteSpace( char* p ) {
436 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
437 ++p;
438 }
439 return p;
440 }
441 static bool IsWhiteSpace( char p ) {
442 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
443 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800444
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700445 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
446 int n = 0;
447 if ( p == q ) {
448 return true;
449 }
450 while( *p && *q && *p == *q && n<nChar ) {
451 ++p;
452 ++q;
453 ++n;
454 }
455 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
456 return true;
457 }
458 return false;
459 }
460 inline static int IsUTF8Continuation( const char p ) {
461 return p & 0x80;
462 }
463 inline static int IsAlphaNum( unsigned char anyByte ) {
464 return ( anyByte < 128 ) ? isalnum( anyByte ) : 1;
465 }
466 inline static int IsAlpha( unsigned char anyByte ) {
467 return ( anyByte < 128 ) ? isalpha( anyByte ) : 1;
468 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800469
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700470 static const char* ReadBOM( const char* p, bool* hasBOM );
471 // p is the starting location,
472 // the UTF-8 value of the entity will be placed in value, and length filled in.
473 static const char* GetCharacterRef( const char* p, char* value, int* length );
474 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700475
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700476 // converts primitive types to strings
477 static void ToStr( int v, char* buffer, int bufferSize );
478 static void ToStr( unsigned v, char* buffer, int bufferSize );
479 static void ToStr( bool v, char* buffer, int bufferSize );
480 static void ToStr( float v, char* buffer, int bufferSize );
481 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700482
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700483 // converts strings to primitive types
484 static bool ToInt( const char* str, int* value );
485 static bool ToUnsigned( const char* str, unsigned* value );
486 static bool ToBool( const char* str, bool* value );
487 static bool ToFloat( const char* str, float* value );
488 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800489};
490
Lee Thomason5cae8972012-01-24 18:03:07 -0800491
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800492/** XMLNode is a base class for every object that is in the
493 XML Document Object Model (DOM), except XMLAttributes.
494 Nodes have siblings, a parent, and children which can
495 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700496 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800497 be cast to its more defined type.
498
Thomas Roß08bdf502012-05-12 14:21:23 +0200499 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800500 When the XMLDocument gets deleted, all its Nodes
501 will also be deleted.
502
503 @verbatim
504 A Document can contain: Element (container or leaf)
505 Comment (leaf)
506 Unknown (leaf)
507 Declaration( leaf )
508
509 An Element can contain: Element (container or leaf)
510 Text (leaf)
511 Attributes (not on tree)
512 Comment (leaf)
513 Unknown (leaf)
514
515 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800516*/
Lee Thomasond1983222012-02-06 08:41:24 -0800517class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800518{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700519 friend class XMLDocument;
520 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800521public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800522
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700523 /// Get the XMLDocument that owns this XMLNode.
524 const XMLDocument* GetDocument() const {
525 return document;
526 }
527 /// Get the XMLDocument that owns this XMLNode.
528 XMLDocument* GetDocument() {
529 return document;
530 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800531
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700532 virtual XMLElement* ToElement() {
533 return 0; ///< Safely cast to an Element, or null.
534 }
535 virtual XMLText* ToText() {
536 return 0; ///< Safely cast to Text, or null.
537 }
538 virtual XMLComment* ToComment() {
539 return 0; ///< Safely cast to a Comment, or null.
540 }
541 virtual XMLDocument* ToDocument() {
542 return 0; ///< Safely cast to a Document, or null.
543 }
544 virtual XMLDeclaration* ToDeclaration() {
545 return 0; ///< Safely cast to a Declaration, or null.
546 }
547 virtual XMLUnknown* ToUnknown() {
548 return 0; ///< Safely cast to an Unknown, or null.
549 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800550
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700551 virtual const XMLElement* ToElement() const {
552 return 0;
553 }
554 virtual const XMLText* ToText() const {
555 return 0;
556 }
557 virtual const XMLComment* ToComment() const {
558 return 0;
559 }
560 virtual const XMLDocument* ToDocument() const {
561 return 0;
562 }
563 virtual const XMLDeclaration* ToDeclaration() const {
564 return 0;
565 }
566 virtual const XMLUnknown* ToUnknown() const {
567 return 0;
568 }
Lee Thomason751da522012-02-10 08:50:51 -0800569
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 /** The meaning of 'value' changes for the specific type.
571 @verbatim
572 Document: empty
573 Element: name of the element
574 Comment: the comment text
575 Unknown: the tag contents
576 Text: the text string
577 @endverbatim
578 */
579 const char* Value() const {
580 return value.GetStr();
581 }
582 /** Set the Value of an XML node.
583 @sa Value()
584 */
585 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800586
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 /// Get the parent of this node on the DOM.
588 const XMLNode* Parent() const {
589 return parent;
590 }
591 XMLNode* Parent() {
592 return parent;
593 }
Lee Thomason751da522012-02-10 08:50:51 -0800594
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 /// Returns true if this node has no children.
596 bool NoChildren() const {
597 return !firstChild;
598 }
Lee Thomason751da522012-02-10 08:50:51 -0800599
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 /// Get the first child node, or null if none exists.
601 const XMLNode* FirstChild() const {
602 return firstChild;
603 }
604 XMLNode* FirstChild() {
605 return firstChild;
606 }
607 /** Get the first child element, or optionally the first child
608 element with the specified name.
609 */
610 const XMLElement* FirstChildElement( const char* value=0 ) const;
611 XMLElement* FirstChildElement( const char* _value=0 ) {
612 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value ));
613 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800614
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700615 /// Get the last child node, or null if none exists.
616 const XMLNode* LastChild() const {
617 return lastChild;
618 }
619 XMLNode* LastChild() {
620 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
621 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800622
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700623 /** Get the last child element or optionally the last child
624 element with the specified name.
625 */
626 const XMLElement* LastChildElement( const char* value=0 ) const;
627 XMLElement* LastChildElement( const char* _value=0 ) {
628 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) );
629 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700630
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700631 /// Get the previous (left) sibling node of this node.
632 const XMLNode* PreviousSibling() const {
633 return prev;
634 }
635 XMLNode* PreviousSibling() {
636 return prev;
637 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800638
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700639 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
640 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
641 XMLElement* PreviousSiblingElement( const char* _value=0 ) {
642 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) );
643 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700644
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 /// Get the next (right) sibling node of this node.
646 const XMLNode* NextSibling() const {
647 return next;
648 }
649 XMLNode* NextSibling() {
650 return next;
651 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700652
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
654 const XMLElement* NextSiblingElement( const char* value=0 ) const;
655 XMLElement* NextSiblingElement( const char* _value=0 ) {
656 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) );
657 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800658
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 /**
660 Add a child node as the last (right) child.
661 */
662 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800663
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 XMLNode* LinkEndChild( XMLNode* addThis ) {
665 return InsertEndChild( addThis );
666 }
667 /**
668 Add a child node as the first (left) child.
669 */
670 XMLNode* InsertFirstChild( XMLNode* addThis );
671 /**
672 Add a node after the specified child node.
673 */
674 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700675
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 /**
677 Delete all the children of this node.
678 */
679 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800680
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 /**
682 Delete a child of this node.
683 */
684 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800685
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 /**
687 Make a copy of this node, but not its children.
688 You may pass in a Document pointer that will be
689 the owner of the new Node. If the 'document' is
690 null, then the node returned will be allocated
691 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800692
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700693 Note: if called on a XMLDocument, this will return null.
694 */
695 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800696
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 /**
698 Test if 2 nodes are the same, but don't test children.
699 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800700
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 Note: if called on a XMLDocument, this will return false.
702 */
703 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
706 XML tree will be conditionally visited and the host will be called back
707 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800708
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
710 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
711 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800712
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 - http://www.saxproject.org/
716 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800717
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800719
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 An example of using Accept():
721 @verbatim
722 TiXmlPrinter printer;
723 tinyxmlDoc.Accept( &printer );
724 const char* xmlcstr = printer.CStr();
725 @endverbatim
726 */
727 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 // internal
730 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800731
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800732protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 XMLNode( XMLDocument* );
734 virtual ~XMLNode();
735 XMLNode( const XMLNode& ); // not supported
736 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 XMLDocument* document;
739 XMLNode* parent;
740 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800741
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 XMLNode* firstChild;
743 XMLNode* lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800744
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 XMLNode* prev;
746 XMLNode* next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800747
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800748private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 MemPool* memPool;
750 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800751};
752
753
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800754/** XML text.
755
756 Note that a text node can have child element nodes, for example:
757 @verbatim
758 <root>This is <b>bold</b></root>
759 @endverbatim
760
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700761 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800762 and CDATA. It will default to the mode it was parsed from the XML file and
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700763 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800764 SetCDATA() and query it with CDATA().
765*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800766class XMLText : public XMLNode
767{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 friend class XMLBase;
769 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800770public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800772
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 virtual XMLText* ToText() {
774 return this;
775 }
776 virtual const XMLText* ToText() const {
777 return this;
778 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800779
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700780 /// Declare whether this should be CDATA or standard text.
781 void SetCData( bool _isCData ) {
782 this->isCData = _isCData;
783 }
784 /// Returns true if this is a CDATA text element.
785 bool CData() const {
786 return isCData;
787 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800788
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 char* ParseDeep( char*, StrPair* endTag );
790 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
791 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800792
Lee Thomason5492a1c2012-01-23 15:32:10 -0800793
794protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700795 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
796 virtual ~XMLText() {}
797 XMLText( const XMLText& ); // not supported
798 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800799
800private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700801 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800802};
803
804
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800805/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800806class XMLComment : public XMLNode
807{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700808 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800809public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700810 virtual XMLComment* ToComment() {
811 return this;
812 }
813 virtual const XMLComment* ToComment() const {
814 return this;
815 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800816
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800818
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 char* ParseDeep( char*, StrPair* endTag );
820 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
821 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800822
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800823protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700824 XMLComment( XMLDocument* doc );
825 virtual ~XMLComment();
826 XMLComment( const XMLComment& ); // not supported
827 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800828
Lee Thomason3f57d272012-01-11 15:30:03 -0800829private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800830};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800831
832
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800833/** In correct XML the declaration is the first entry in the file.
834 @verbatim
835 <?xml version="1.0" standalone="yes"?>
836 @endverbatim
837
838 TinyXML2 will happily read or write files without a declaration,
839 however.
840
841 The text of the declaration isn't interpreted. It is parsed
842 and written as a string.
843*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800844class XMLDeclaration : public XMLNode
845{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800847public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700848 virtual XMLDeclaration* ToDeclaration() {
849 return this;
850 }
851 virtual const XMLDeclaration* ToDeclaration() const {
852 return this;
853 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800854
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800856
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 char* ParseDeep( char*, StrPair* endTag );
858 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
859 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800860
861protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700862 XMLDeclaration( XMLDocument* doc );
863 virtual ~XMLDeclaration();
864 XMLDeclaration( const XMLDeclaration& ); // not supported
865 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800866};
867
868
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800869/** Any tag that tinyXml doesn't recognize is saved as an
870 unknown. It is a tag of text, but should not be modified.
871 It will be written back to the XML, unchanged, when the file
872 is saved.
873
874 DTD tags get thrown into TiXmlUnknowns.
875*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800876class XMLUnknown : public XMLNode
877{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700878 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800879public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700880 virtual XMLUnknown* ToUnknown() {
881 return this;
882 }
883 virtual const XMLUnknown* ToUnknown() const {
884 return this;
885 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800886
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700887 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800888
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700889 char* ParseDeep( char*, StrPair* endTag );
890 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
891 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800892
893protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700894 XMLUnknown( XMLDocument* doc );
895 virtual ~XMLUnknown();
896 XMLUnknown( const XMLUnknown& ); // not supported
897 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800898};
899
900
Lee Thomason1ff38e02012-02-14 18:18:16 -0800901enum {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700902 XML_NO_ERROR = 0,
903 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800904
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700905 XML_NO_ATTRIBUTE,
906 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800907
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700908 XML_ERROR_FILE_NOT_FOUND,
909 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
910 XML_ERROR_FILE_READ_ERROR,
911 XML_ERROR_ELEMENT_MISMATCH,
912 XML_ERROR_PARSING_ELEMENT,
913 XML_ERROR_PARSING_ATTRIBUTE,
914 XML_ERROR_IDENTIFYING_TAG,
915 XML_ERROR_PARSING_TEXT,
916 XML_ERROR_PARSING_CDATA,
917 XML_ERROR_PARSING_COMMENT,
918 XML_ERROR_PARSING_DECLARATION,
919 XML_ERROR_PARSING_UNKNOWN,
920 XML_ERROR_EMPTY_DOCUMENT,
921 XML_ERROR_MISMATCHED_ELEMENT,
922 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700923
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700924 XML_CAN_NOT_CONVERT_TEXT,
925 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800926};
927
928
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800929/** An attribute is a name-value pair. Elements have an arbitrary
930 number of attributes, each with a unique name.
931
932 @note The attributes are not XMLNodes. You may only query the
933 Next() attribute in a list.
934*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800935class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800936{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700937 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800938public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700939 const char* Name() const {
940 return name.GetStr(); ///< The name of the attribute.
941 }
942 const char* Value() const {
943 return value.GetStr(); ///< The value of the attribute.
944 }
945 const XMLAttribute* Next() const {
946 return next; ///< The next attribute in the list.
947 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800948
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700949 /** IntAttribute interprets the attribute as an integer, and returns the value.
950 If the value isn't an integer, 0 will be returned. There is no error checking;
951 use QueryIntAttribute() if you need error checking.
952 */
953 int IntValue() const {
954 int i=0;
955 QueryIntValue( &i );
956 return i;
957 }
958 /// Query as an unsigned integer. See IntAttribute()
959 unsigned UnsignedValue() const {
960 unsigned i=0;
961 QueryUnsignedValue( &i );
962 return i;
963 }
964 /// Query as a boolean. See IntAttribute()
965 bool BoolValue() const {
966 bool b=false;
967 QueryBoolValue( &b );
968 return b;
969 }
970 /// Query as a double. See IntAttribute()
971 double DoubleValue() const {
972 double d=0;
973 QueryDoubleValue( &d );
974 return d;
975 }
976 /// Query as a float. See IntAttribute()
977 float FloatValue() const {
978 float f=0;
979 QueryFloatValue( &f );
980 return f;
981 }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800982
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
984 in the provided paremeter. The function will return XML_NO_ERROR on success,
985 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
986 */
987 int QueryIntValue( int* value ) const;
988 /// See QueryIntAttribute
989 int QueryUnsignedValue( unsigned int* value ) const;
990 /// See QueryIntAttribute
991 int QueryBoolValue( bool* value ) const;
992 /// See QueryIntAttribute
993 int QueryDoubleValue( double* value ) const;
994 /// See QueryIntAttribute
995 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800996
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700997 /// Set the attribute to a string value.
998 void SetAttribute( const char* value );
999 /// Set the attribute to value.
1000 void SetAttribute( int value );
1001 /// Set the attribute to value.
1002 void SetAttribute( unsigned value );
1003 /// Set the attribute to value.
1004 void SetAttribute( bool value );
1005 /// Set the attribute to value.
1006 void SetAttribute( double value );
1007 /// Set the attribute to value.
1008 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001009
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001010private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001011 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001012
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001013 XMLAttribute() : next( 0 ) {}
1014 virtual ~XMLAttribute() {}
1015 XMLAttribute( const XMLAttribute& ); // not supported
1016 void operator=( const XMLAttribute& ); // not supported
1017 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001018
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001020
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001021 mutable StrPair name;
1022 mutable StrPair value;
1023 XMLAttribute* next;
1024 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001025};
1026
1027
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001028/** The element is a container class. It has a value, the element name,
1029 and can contain other elements, text, comments, and unknowns.
1030 Elements also contain an arbitrary number of attributes.
1031*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001032class XMLElement : public XMLNode
1033{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001034 friend class XMLBase;
1035 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001036public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001037 /// Get the name of an element (which is the Value() of the node.)
1038 const char* Name() const {
1039 return Value();
1040 }
1041 /// Set the name of the element.
1042 void SetName( const char* str, bool staticMem=false ) {
1043 SetValue( str, staticMem );
1044 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001045
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001046 virtual XMLElement* ToElement() {
1047 return this;
1048 }
1049 virtual const XMLElement* ToElement() const {
1050 return this;
1051 }
1052 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001053
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001054 /** Given an attribute name, Attribute() returns the value
1055 for the attribute of that name, or null if none
1056 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001057
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001058 @verbatim
1059 const char* value = ele->Attribute( "foo" );
1060 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001061
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001062 The 'value' parameter is normally null. However, if specified,
1063 the attribute will only be returned if the 'name' and 'value'
1064 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001065
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001066 @verbatim
1067 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1068 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001069
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001070 rather than:
1071 @verbatim
1072 if ( ele->Attribute( "foo" ) ) {
1073 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1074 }
1075 @endverbatim
1076 */
1077 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001078
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001079 /** Given an attribute name, IntAttribute() returns the value
1080 of the attribute interpreted as an integer. 0 will be
1081 returned if there is an error. For a method with error
1082 checking, see QueryIntAttribute()
1083 */
1084 int IntAttribute( const char* name ) const {
1085 int i=0;
1086 QueryIntAttribute( name, &i );
1087 return i;
1088 }
1089 /// See IntAttribute()
1090 unsigned UnsignedAttribute( const char* name ) const {
1091 unsigned i=0;
1092 QueryUnsignedAttribute( name, &i );
1093 return i;
1094 }
1095 /// See IntAttribute()
1096 bool BoolAttribute( const char* name ) const {
1097 bool b=false;
1098 QueryBoolAttribute( name, &b );
1099 return b;
1100 }
1101 /// See IntAttribute()
1102 double DoubleAttribute( const char* name ) const {
1103 double d=0;
1104 QueryDoubleAttribute( name, &d );
1105 return d;
1106 }
1107 /// See IntAttribute()
1108 float FloatAttribute( const char* name ) const {
1109 float f=0;
1110 QueryFloatAttribute( name, &f );
1111 return f;
1112 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001113
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001114 /** Given an attribute name, QueryIntAttribute() returns
1115 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1116 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1117 doesn't exist. If successful, the result of the conversion
1118 will be written to 'value'. If not successful, nothing will
1119 be written to 'value'. This allows you to provide default
1120 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001121
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001122 @verbatim
1123 int value = 10;
1124 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1125 @endverbatim
1126 */
1127 int QueryIntAttribute( const char* name, int* _value ) const {
1128 const XMLAttribute* a = FindAttribute( name );
1129 if ( !a ) {
1130 return XML_NO_ATTRIBUTE;
1131 }
1132 return a->QueryIntValue( _value );
1133 }
1134 /// See QueryIntAttribute()
1135 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const {
1136 const XMLAttribute* a = FindAttribute( name );
1137 if ( !a ) {
1138 return XML_NO_ATTRIBUTE;
1139 }
1140 return a->QueryUnsignedValue( _value );
1141 }
1142 /// See QueryIntAttribute()
1143 int QueryBoolAttribute( const char* name, bool* _value ) const {
1144 const XMLAttribute* a = FindAttribute( name );
1145 if ( !a ) {
1146 return XML_NO_ATTRIBUTE;
1147 }
1148 return a->QueryBoolValue( _value );
1149 }
1150 /// See QueryIntAttribute()
1151 int QueryDoubleAttribute( const char* name, double* _value ) const {
1152 const XMLAttribute* a = FindAttribute( name );
1153 if ( !a ) {
1154 return XML_NO_ATTRIBUTE;
1155 }
1156 return a->QueryDoubleValue( _value );
1157 }
1158 /// See QueryIntAttribute()
1159 int QueryFloatAttribute( const char* name, float* _value ) const {
1160 const XMLAttribute* a = FindAttribute( name );
1161 if ( !a ) {
1162 return XML_NO_ATTRIBUTE;
1163 }
1164 return a->QueryFloatValue( _value );
1165 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001166
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001167 /// Sets the named attribute to value.
1168 void SetAttribute( const char* name, const char* _value ) {
1169 XMLAttribute* a = FindOrCreateAttribute( name );
1170 a->SetAttribute( _value );
1171 }
1172 /// Sets the named attribute to value.
1173 void SetAttribute( const char* name, int _value ) {
1174 XMLAttribute* a = FindOrCreateAttribute( name );
1175 a->SetAttribute( _value );
1176 }
1177 /// Sets the named attribute to value.
1178 void SetAttribute( const char* name, unsigned _value ) {
1179 XMLAttribute* a = FindOrCreateAttribute( name );
1180 a->SetAttribute( _value );
1181 }
1182 /// Sets the named attribute to value.
1183 void SetAttribute( const char* name, bool _value ) {
1184 XMLAttribute* a = FindOrCreateAttribute( name );
1185 a->SetAttribute( _value );
1186 }
1187 /// Sets the named attribute to value.
1188 void SetAttribute( const char* name, double _value ) {
1189 XMLAttribute* a = FindOrCreateAttribute( name );
1190 a->SetAttribute( _value );
1191 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001192
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001193 /**
1194 Delete an attribute.
1195 */
1196 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001197
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001198 /// Return the first attribute in the list.
1199 const XMLAttribute* FirstAttribute() const {
1200 return rootAttribute;
1201 }
1202 /// Query a specific attribute in the list.
1203 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001204
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001205 /** Convenience function for easy access to the text inside an element. Although easy
1206 and concise, GetText() is limited compared to getting the TiXmlText child
1207 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001208
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 If the first child of 'this' is a TiXmlText, the GetText()
1210 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001211
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 This is a convenient method for getting the text of simple contained text:
1213 @verbatim
1214 <foo>This is text</foo>
1215 const char* str = fooElement->GetText();
1216 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001217
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001219
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 Note that this function can be misleading. If the element foo was created from
1221 this XML:
1222 @verbatim
1223 <foo><b>This is text</b></foo>
1224 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001225
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001226 then the value of str would be null. The first child node isn't a text node, it is
1227 another element. From this XML:
1228 @verbatim
1229 <foo>This is <b>text</b></foo>
1230 @endverbatim
1231 GetText() will return "This is ".
1232 */
1233 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001234
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 /**
1236 Convenience method to query the value of a child text node. This is probably best
1237 shown by example. Given you have a document is this form:
1238 @verbatim
1239 <point>
1240 <x>1</x>
1241 <y>1.4</y>
1242 </point>
1243 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001244
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001245 The QueryIntText() and similar functions provide a safe and easier way to get to the
1246 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001247
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001248 @verbatim
1249 int x = 0;
1250 float y = 0; // types of x and y are contrived for example
1251 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1252 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1253 xElement->QueryIntText( &x );
1254 yElement->QueryFloatText( &y );
1255 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001256
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1258 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001259
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 */
1261 int QueryIntText( int* _value ) const;
1262 /// See QueryIntText()
1263 int QueryUnsignedText( unsigned* _value ) const;
1264 /// See QueryIntText()
1265 int QueryBoolText( bool* _value ) const;
1266 /// See QueryIntText()
1267 int QueryDoubleText( double* _value ) const;
1268 /// See QueryIntText()
1269 int QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001270
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 // internal:
1272 enum {
1273 OPEN, // <foo>
1274 CLOSED, // <foo/>
1275 CLOSING // </foo>
1276 };
1277 int ClosingType() const {
1278 return closingType;
1279 }
1280 char* ParseDeep( char* p, StrPair* endTag );
1281 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1282 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001283
Lee Thomason50adb4c2012-02-13 15:07:09 -08001284private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 XMLElement( XMLDocument* doc );
1286 virtual ~XMLElement();
1287 XMLElement( const XMLElement& ); // not supported
1288 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001289
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 XMLAttribute* FindAttribute( const char* name );
1291 XMLAttribute* FindOrCreateAttribute( const char* name );
1292 //void LinkAttribute( XMLAttribute* attrib );
1293 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001294
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 int closingType;
1296 // The attribute list is ordered; there is no 'lastAttribute'
1297 // because the list needs to be scanned for dupes before adding
1298 // a new attribute.
1299 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001300};
1301
1302
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001303enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 PRESERVE_WHITESPACE,
1305 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001306};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001307
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001308
1309/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001310 It can be saved, loaded, and printed to the screen.
1311 All Nodes are connected and allocated to a Document.
1312 If the Document is deleted, all its Nodes are also deleted.
1313*/
Lee Thomason67d61312012-01-24 16:01:51 -08001314class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001315{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001317public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 /// constructor
1319 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1320 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001321
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 virtual XMLDocument* ToDocument() {
1323 return this;
1324 }
1325 virtual const XMLDocument* ToDocument() const {
1326 return this;
1327 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001328
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 /**
1330 Parse an XML file from a character string.
1331 Returns XML_NO_ERROR (0) on success, or
1332 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001333
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001334 You may optionally pass in the 'nBytes', which is
1335 the number of bytes which will be parsed. If not
1336 specified, TinyXML will assume 'xml' points to a
1337 null terminated string.
1338 */
1339 int Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001340
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 /**
1342 Load an XML file from disk.
1343 Returns XML_NO_ERROR (0) on success, or
1344 an errorID.
1345 */
1346 int LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001347
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001348 /**
1349 Load an XML file from disk. You are responsible
1350 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001351
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 Returns XML_NO_ERROR (0) on success, or
1353 an errorID.
1354 */
1355 int LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001356
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001357 /**
1358 Save the XML file to disk.
1359 Returns XML_NO_ERROR (0) on success, or
1360 an errorID.
1361 */
1362 int SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001363
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 /**
1365 Save the XML file to disk. You are responsible
1366 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001367
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001368 Returns XML_NO_ERROR (0) on success, or
1369 an errorID.
1370 */
1371 int SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001372
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 bool ProcessEntities() const {
1374 return processEntities;
1375 }
1376 Whitespace WhitespaceMode() const {
1377 return whitespace;
1378 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001379
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /**
1381 Returns true if this document has a leading Byte Order Mark of UTF8.
1382 */
1383 bool HasBOM() const {
1384 return writeBOM;
1385 }
1386 /** Sets whether to write the BOM when writing the file.
1387 */
1388 void SetBOM( bool useBOM ) {
1389 writeBOM = useBOM;
1390 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001391
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001392 /** Return the root element of DOM. Equivalent to FirstChildElement().
1393 To get the first node, use FirstChild().
1394 */
1395 XMLElement* RootElement() {
1396 return FirstChildElement();
1397 }
1398 const XMLElement* RootElement() const {
1399 return FirstChildElement();
1400 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001401
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001402 /** Print the Document. If the Printer is not provided, it will
1403 print to stdout. If you provide Printer, this can print to a file:
1404 @verbatim
1405 XMLPrinter printer( fp );
1406 doc.Print( &printer );
1407 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001408
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001409 Or you can use a printer to print to memory:
1410 @verbatim
1411 XMLPrinter printer;
1412 doc->Print( &printer );
1413 // printer.CStr() has a const char* to the XML
1414 @endverbatim
1415 */
1416 void Print( XMLPrinter* streamer=0 );
1417 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001418
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001419 /**
1420 Create a new Element associated with
1421 this Document. The memory for the Element
1422 is managed by the Document.
1423 */
1424 XMLElement* NewElement( const char* name );
1425 /**
1426 Create a new Comment associated with
1427 this Document. The memory for the Comment
1428 is managed by the Document.
1429 */
1430 XMLComment* NewComment( const char* comment );
1431 /**
1432 Create a new Text associated with
1433 this Document. The memory for the Text
1434 is managed by the Document.
1435 */
1436 XMLText* NewText( const char* text );
1437 /**
1438 Create a new Declaration associated with
1439 this Document. The memory for the object
1440 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 If the 'text' param is null, the standard
1443 declaration is used.:
1444 @verbatim
1445 <?xml version="1.0" encoding="UTF-8"?>
1446 @endverbatim
1447 */
1448 XMLDeclaration* NewDeclaration( const char* text=0 );
1449 /**
1450 Create a new Unknown associated with
1451 this Document. The memory for the object
1452 is managed by the Document.
1453 */
1454 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001455
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001456 /**
1457 Delete a node associated with this document.
1458 It will be unlinked from the DOM.
1459 */
1460 void DeleteNode( XMLNode* node ) {
1461 node->parent->DeleteChild( node );
1462 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001463
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001464 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001465
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001466 /// Return true if there was an error parsing the document.
1467 bool Error() const {
1468 return errorID != XML_NO_ERROR;
1469 }
1470 /// Return the errorID.
1471 int ErrorID() const {
1472 return errorID;
1473 }
1474 /// Return a possibly helpful diagnostic location or string.
1475 const char* GetErrorStr1() const {
1476 return errorStr1;
1477 }
1478 /// Return a possibly helpful secondary diagnostic location or string.
1479 const char* GetErrorStr2() const {
1480 return errorStr2;
1481 }
1482 /// If there is an error, print it to stdout.
1483 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001484
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001485 // internal
1486 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001487
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1489 return 0;
1490 }
1491 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1492 return false;
1493 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001494
Lee Thomason3f57d272012-01-11 15:30:03 -08001495private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 XMLDocument( const XMLDocument& ); // not supported
1497 void operator=( const XMLDocument& ); // not supported
1498 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001499
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001500 bool writeBOM;
1501 bool processEntities;
1502 int errorID;
1503 Whitespace whitespace;
1504 const char* errorStr1;
1505 const char* errorStr2;
1506 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 MemPoolT< sizeof(XMLElement) > elementPool;
1509 MemPoolT< sizeof(XMLAttribute) > attributePool;
1510 MemPoolT< sizeof(XMLText) > textPool;
1511 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001512};
1513
Lee Thomason7c913cd2012-01-26 18:32:34 -08001514
Lee Thomason3ffdd392012-03-28 17:27:55 -07001515/**
1516 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001517 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001518 DOM structure. It is a separate utility class.
1519
1520 Take an example:
1521 @verbatim
1522 <Document>
1523 <Element attributeA = "valueA">
1524 <Child attributeB = "value1" />
1525 <Child attributeB = "value2" />
1526 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001527 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001528 @endverbatim
1529
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001530 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001531 easy to write a *lot* of code that looks like:
1532
1533 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001534 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001535 if ( root )
1536 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001537 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001538 if ( element )
1539 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001540 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001541 if ( child )
1542 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001543 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001544 if ( child2 )
1545 {
1546 // Finally do something useful.
1547 @endverbatim
1548
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001549 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001550 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001551 and correct to use:
1552
1553 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001554 XMLHandle docHandle( &document );
1555 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001556 if ( child2 )
1557 {
1558 // do something useful
1559 @endverbatim
1560
1561 Which is MUCH more concise and useful.
1562
1563 It is also safe to copy handles - internally they are nothing more than node pointers.
1564 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001565 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001566 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001567
1568 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001569*/
1570class XMLHandle
1571{
1572public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001573 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1574 XMLHandle( XMLNode* _node ) {
1575 node = _node;
1576 }
1577 /// Create a handle from a node.
1578 XMLHandle( XMLNode& _node ) {
1579 node = &_node;
1580 }
1581 /// Copy constructor
1582 XMLHandle( const XMLHandle& ref ) {
1583 node = ref.node;
1584 }
1585 /// Assignment
1586 XMLHandle& operator=( const XMLHandle& ref ) {
1587 node = ref.node;
1588 return *this;
1589 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001590
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001591 /// Get the first child of this handle.
1592 XMLHandle FirstChild() {
1593 return XMLHandle( node ? node->FirstChild() : 0 );
1594 }
1595 /// Get the first child element of this handle.
1596 XMLHandle FirstChildElement( const char* value=0 ) {
1597 return XMLHandle( node ? node->FirstChildElement( value ) : 0 );
1598 }
1599 /// Get the last child of this handle.
1600 XMLHandle LastChild() {
1601 return XMLHandle( node ? node->LastChild() : 0 );
1602 }
1603 /// Get the last child element of this handle.
1604 XMLHandle LastChildElement( const char* _value=0 ) {
1605 return XMLHandle( node ? node->LastChildElement( _value ) : 0 );
1606 }
1607 /// Get the previous sibling of this handle.
1608 XMLHandle PreviousSibling() {
1609 return XMLHandle( node ? node->PreviousSibling() : 0 );
1610 }
1611 /// Get the previous sibling element of this handle.
1612 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
1613 return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 );
1614 }
1615 /// Get the next sibling of this handle.
1616 XMLHandle NextSibling() {
1617 return XMLHandle( node ? node->NextSibling() : 0 );
1618 }
1619 /// Get the next sibling element of this handle.
1620 XMLHandle NextSiblingElement( const char* _value=0 ) {
1621 return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 );
1622 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001623
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001624 /// Safe cast to XMLNode. This can return null.
1625 XMLNode* ToNode() {
1626 return node;
1627 }
1628 /// Safe cast to XMLElement. This can return null.
1629 XMLElement* ToElement() {
1630 return ( ( node && node->ToElement() ) ? node->ToElement() : 0 );
1631 }
1632 /// Safe cast to XMLText. This can return null.
1633 XMLText* ToText() {
1634 return ( ( node && node->ToText() ) ? node->ToText() : 0 );
1635 }
1636 /// Safe cast to XMLUnknown. This can return null.
1637 XMLUnknown* ToUnknown() {
1638 return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 );
1639 }
1640 /// Safe cast to XMLDeclaration. This can return null.
1641 XMLDeclaration* ToDeclaration() {
1642 return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 );
1643 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001644
1645private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 XMLNode* node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001647};
1648
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001649
1650/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001651 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1652 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001653*/
1654class XMLConstHandle
1655{
1656public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 XMLConstHandle( const XMLNode* _node ) {
1658 node = _node;
1659 }
1660 XMLConstHandle( const XMLNode& _node ) {
1661 node = &_node;
1662 }
1663 XMLConstHandle( const XMLConstHandle& ref ) {
1664 node = ref.node;
1665 }
Lee Thomason8b899812012-04-04 15:58:16 -07001666
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
1668 node = ref.node;
1669 return *this;
1670 }
Lee Thomason8b899812012-04-04 15:58:16 -07001671
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001672 const XMLConstHandle FirstChild() const {
1673 return XMLConstHandle( node ? node->FirstChild() : 0 );
1674 }
1675 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
1676 return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 );
1677 }
1678 const XMLConstHandle LastChild() const {
1679 return XMLConstHandle( node ? node->LastChild() : 0 );
1680 }
1681 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
1682 return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 );
1683 }
1684 const XMLConstHandle PreviousSibling() const {
1685 return XMLConstHandle( node ? node->PreviousSibling() : 0 );
1686 }
1687 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
1688 return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 );
1689 }
1690 const XMLConstHandle NextSibling() const {
1691 return XMLConstHandle( node ? node->NextSibling() : 0 );
1692 }
1693 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
1694 return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 );
1695 }
Lee Thomason8b899812012-04-04 15:58:16 -07001696
1697
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001698 const XMLNode* ToNode() const {
1699 return node;
1700 }
1701 const XMLElement* ToElement() const {
1702 return ( ( node && node->ToElement() ) ? node->ToElement() : 0 );
1703 }
1704 const XMLText* ToText() const {
1705 return ( ( node && node->ToText() ) ? node->ToText() : 0 );
1706 }
1707 const XMLUnknown* ToUnknown() const {
1708 return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 );
1709 }
1710 const XMLDeclaration* ToDeclaration() const {
1711 return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 );
1712 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001713
Lee Thomason5cae8972012-01-24 18:03:07 -08001714private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 const XMLNode* node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001716};
Lee Thomason6f381b72012-03-02 12:59:39 -08001717
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001718
1719/**
1720 Printing functionality. The XMLPrinter gives you more
1721 options than the XMLDocument::Print() method.
1722
1723 It can:
1724 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001725 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001726 -# Print XML without a XMLDocument.
1727
1728 Print to Memory
1729
1730 @verbatim
1731 XMLPrinter printer;
1732 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001733 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001734 @endverbatim
1735
1736 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001737
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001738 You provide the file pointer.
1739 @verbatim
1740 XMLPrinter printer( fp );
1741 doc.Print( &printer );
1742 @endverbatim
1743
1744 Print without a XMLDocument
1745
1746 When loading, an XML parser is very useful. However, sometimes
1747 when saving, it just gets in the way. The code is often set up
1748 for streaming, and constructing the DOM is just overhead.
1749
1750 The Printer supports the streaming case. The following code
1751 prints out a trivially simple XML file without ever creating
1752 an XML document.
1753
1754 @verbatim
1755 XMLPrinter printer( fp );
1756 printer.OpenElement( "foo" );
1757 printer.PushAttribute( "foo", "bar" );
1758 printer.CloseElement();
1759 @endverbatim
1760*/
1761class XMLPrinter : public XMLVisitor
1762{
1763public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001764 /** Construct the printer. If the FILE* is specified,
1765 this will print to the FILE. Else it will print
1766 to memory, and the result is available in CStr().
1767 If 'compact' is set to true, then output is created
1768 with only required whitespace and newlines.
1769 */
1770 XMLPrinter( FILE* file=0, bool compact = false );
1771 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001772
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001773 /** If streaming, write the BOM and declaration. */
1774 void PushHeader( bool writeBOM, bool writeDeclaration );
1775 /** If streaming, start writing an element.
1776 The element must be closed with CloseElement()
1777 */
1778 void OpenElement( const char* name );
1779 /// If streaming, add an attribute to an open element.
1780 void PushAttribute( const char* name, const char* value );
1781 void PushAttribute( const char* name, int value );
1782 void PushAttribute( const char* name, unsigned value );
1783 void PushAttribute( const char* name, bool value );
1784 void PushAttribute( const char* name, double value );
1785 /// If streaming, close the Element.
1786 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001787
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001788 /// Add a text node.
1789 void PushText( const char* text, bool cdata=false );
1790 /// Add a text node from an integer.
1791 void PushText( int value );
1792 /// Add a text node from an unsigned.
1793 void PushText( unsigned value );
1794 /// Add a text node from a bool.
1795 void PushText( bool value );
1796 /// Add a text node from a float.
1797 void PushText( float value );
1798 /// Add a text node from a double.
1799 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001800
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001801 /// Add a comment
1802 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001803
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001804 void PushDeclaration( const char* value );
1805 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001806
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1808 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1809 return true;
1810 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001811
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001812 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1813 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001814
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001815 virtual bool Visit( const XMLText& text );
1816 virtual bool Visit( const XMLComment& comment );
1817 virtual bool Visit( const XMLDeclaration& declaration );
1818 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001819
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001820 /**
1821 If in print to memory mode, return a pointer to
1822 the XML file in memory.
1823 */
1824 const char* CStr() const {
1825 return buffer.Mem();
1826 }
1827 /**
1828 If in print to memory mode, return the size
1829 of the XML file in memory. (Note the size returned
1830 includes the terminating null.)
1831 */
1832 int CStrSize() const {
1833 return buffer.Size();
1834 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001835
1836private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001837 void SealElement();
1838 void PrintSpace( int depth );
1839 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1840 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001841
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001842 bool elementJustOpened;
1843 bool firstElement;
1844 FILE* fp;
1845 int depth;
1846 int textDepth;
1847 bool processEntities;
1848 bool compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001849
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001850 enum {
1851 ENTITY_RANGE = 64,
1852 BUF_SIZE = 200
1853 };
1854 bool entityFlag[ENTITY_RANGE];
1855 bool restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001856
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001857 DynArray< const char*, 10 > stack;
1858 DynArray< char, 20 > buffer;
PKEuSe736f292012-07-16 03:27:55 -07001859#ifdef _MSC_VER
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001860 DynArray< char, 20 > accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001861#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001862};
1863
1864
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001865} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001866
1867
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001868#endif // TINYXML2_INCLUDED