blob: e90d60fe66156bdf7cd7ea81b324cb894060664a [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 Thomason5e3803c2012-04-16 08:57:05 -070027#include <cctype>
28#include <climits>
29#include <cstdio>
30#include <cstring>
31#include <cstdarg>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070032
Lee Thomason7d00b9a2012-02-27 17:54:22 -080033/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080034 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080035*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080036/*
37 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
38*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080039
U-Lama\Lee4cee6112011-12-31 14:58:18 -080040#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
41 #ifndef DEBUG
42 #define DEBUG
43 #endif
44#endif
45
46
47#if defined(DEBUG)
48 #if defined(_MSC_VER)
Guillermo A. Amaral68b0c872012-03-24 11:07:19 -070049 #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
U-Lama\Lee4cee6112011-12-31 14:58:18 -080050 #elif defined (ANDROID_NDK)
51 #include <android/log.h>
52 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
53 #else
54 #include <assert.h>
55 #define TIXMLASSERT assert
56 #endif
57#else
58 #define TIXMLASSERT( x ) {}
59#endif
60
U-Lama\Leee13c3e62011-12-28 14:36:55 -080061
Lee Thomason1a1d4a72012-02-15 09:09:25 -080062#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
63 // Microsoft visual studio, version 2005 and higher.
Lee Thomason (grinliz)598c13e2012-04-06 21:18:23 -070064 /*int _snprintf_s(
65 char *buffer,
66 size_t sizeOfBuffer,
67 size_t count,
68 const char *format [,
69 argument] ...
70 );*/
71 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
72 va_list va;
73 va_start( va, format );
74 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
75 va_end( va );
76 return result;
77 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -080078 #define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070079#else
U-Stream\Leeae25a442012-02-17 17:48:16 -080080 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080081 //#warning( "Using sn* functions." )
82 #define TIXML_SNPRINTF snprintf
83 #define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080084#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080085
Lee Thomason78d450b2012-06-04 17:05:58 -070086static const int TIXML2_MAJOR_VERSION = 1;
87static const int TIXML2_MINOR_VERSION = 0;
Lee Thomasona3efec02012-06-15 14:30:44 -070088static const int TIXML2_PATCH_VERSION = 3;
Lee Thomason1ff38e02012-02-14 18:18:16 -080089
U-Lama\Leee13c3e62011-12-28 14:36:55 -080090namespace tinyxml2
91{
Lee Thomasonce0763e2012-01-11 15:43:54 -080092class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080093class XMLElement;
94class XMLAttribute;
95class XMLComment;
96class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080097class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080098class XMLDeclaration;
99class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800100
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800101class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800102
U-Stream\Leeae25a442012-02-17 17:48:16 -0800103/*
104 A class that wraps strings. Normally stores the start and end
105 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800106 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800107 manage) a traditional char[]
108*/
Lee Thomason39ede242012-01-20 11:27:56 -0800109class StrPair
110{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800111public:
Lee Thomason39ede242012-01-20 11:27:56 -0800112 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800113 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800114 NEEDS_NEWLINE_NORMALIZATION = 0x02,
115
116 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800117 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800118 ATTRIBUTE_NAME = 0,
119 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800120 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700121 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomason39ede242012-01-20 11:27:56 -0800122 };
123
124 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800125 ~StrPair();
126
Lee Thomason5ce89412012-03-20 13:23:44 -0700127 void Set( char* _start, char* _end, int _flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800128 Reset();
Lee Thomason5ce89412012-03-20 13:23:44 -0700129 this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
Lee Thomason39ede242012-01-20 11:27:56 -0800130 }
131 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800132 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800133
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700134 void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800135 void SetStr( const char* str, int flags=0 );
136
Lee Thomason56bdd022012-02-09 18:16:58 -0800137 char* ParseText( char* in, const char* endTag, int strFlags );
138 char* ParseName( char* in );
139
Lee Thomason2c85a712012-01-31 08:24:24 -0800140
Lee Thomason39ede242012-01-20 11:27:56 -0800141private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142 void Reset();
143
Lee Thomasone4422302012-01-20 17:59:50 -0800144 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800145 NEEDS_FLUSH = 0x100,
146 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800147 };
148
Lee Thomason39ede242012-01-20 11:27:56 -0800149 // After parsing, if *end != 0, it can be set to zero.
150 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800151 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800152 char* end;
153};
154
U-Lama\Lee560bd472011-12-28 19:42:49 -0800155
U-Stream\Leeae25a442012-02-17 17:48:16 -0800156/*
157 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
158 Has a small initial memory pool, so that low or no usage will not
159 cause a call to new/delete
160*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800161template <class T, int INIT>
162class DynArray
163{
164public:
165 DynArray< T, INIT >()
166 {
167 mem = pool;
168 allocated = INIT;
169 size = 0;
170 }
171 ~DynArray()
172 {
173 if ( mem != pool ) {
Lee Thomasona2ae54e2012-05-18 13:47:48 -0700174 delete [] mem;
Lee Thomason2c85a712012-01-31 08:24:24 -0800175 }
176 }
177 void Push( T t )
178 {
179 EnsureCapacity( size+1 );
180 mem[size++] = t;
181 }
182
183 T* PushArr( int count )
184 {
185 EnsureCapacity( size+count );
186 T* ret = &mem[size];
187 size += count;
188 return ret;
189 }
190 T Pop() {
191 return mem[--size];
192 }
193 void PopArr( int count )
194 {
195 TIXMLASSERT( size >= count );
196 size -= count;
197 }
198
U-Stream\Leeae25a442012-02-17 17:48:16 -0800199 bool Empty() const { return size == 0; }
200 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
201 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
202 int Size() const { return size; }
203 int Capacity() const { return allocated; }
204 const T* Mem() const { return mem; }
205 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800206
207
208private:
209 void EnsureCapacity( int cap ) {
210 if ( cap > allocated ) {
211 int newAllocated = cap * 2;
212 T* newMem = new T[newAllocated];
213 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
214 if ( mem != pool ) delete [] mem;
215 mem = newMem;
216 allocated = newAllocated;
217 }
218 }
219
220 T* mem;
221 T pool[INIT];
222 int allocated; // objects allocated
223 int size; // number objects in use
224};
225
Lee Thomason50adb4c2012-02-13 15:07:09 -0800226
U-Stream\Leeae25a442012-02-17 17:48:16 -0800227/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200228 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800229 and deallocation of objects.
230*/
Lee Thomasond1983222012-02-06 08:41:24 -0800231class MemPool
232{
233public:
234 MemPool() {}
235 virtual ~MemPool() {}
236
237 virtual int ItemSize() const = 0;
238 virtual void* Alloc() = 0;
239 virtual void Free( void* ) = 0;
240};
241
Lee Thomason50adb4c2012-02-13 15:07:09 -0800242
U-Stream\Leeae25a442012-02-17 17:48:16 -0800243/*
244 Template child class to create pools of the correct type.
245*/
Lee Thomasond1983222012-02-06 08:41:24 -0800246template< int SIZE >
247class MemPoolT : public MemPool
248{
249public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800250 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800251 ~MemPoolT() {
252 // Delete the blocks.
253 for( int i=0; i<blockPtrs.Size(); ++i ) {
254 delete blockPtrs[i];
255 }
256 }
257
258 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800259 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800260
261 virtual void* Alloc() {
262 if ( !root ) {
263 // Need a new block.
264 Block* block = new Block();
265 blockPtrs.Push( block );
266
267 for( int i=0; i<COUNT-1; ++i ) {
268 block->chunk[i].next = &block->chunk[i+1];
269 }
270 block->chunk[COUNT-1].next = 0;
271 root = block->chunk;
272 }
273 void* result = root;
274 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800275
276 ++currentAllocs;
277 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
278 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800279 return result;
280 }
281 virtual void Free( void* mem ) {
282 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800283 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800284 Chunk* chunk = (Chunk*)mem;
285 memset( chunk, 0xfe, sizeof(Chunk) );
286 chunk->next = root;
287 root = chunk;
288 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800289 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800290 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
291 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800292 }
Lee Thomasond1983222012-02-06 08:41:24 -0800293
294private:
295 enum { COUNT = 1024/SIZE };
296 union Chunk {
297 Chunk* next;
298 char mem[SIZE];
299 };
300 struct Block {
301 Chunk chunk[COUNT];
302 };
303 DynArray< Block*, 10 > blockPtrs;
304 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800305
306 int currentAllocs;
307 int nAllocs;
308 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800309};
310
Lee Thomason2c85a712012-01-31 08:24:24 -0800311
Lee Thomason56bdd022012-02-09 18:16:58 -0800312
313/**
314 Implements the interface to the "Visitor pattern" (see the Accept() method.)
315 If you call the Accept() method, it requires being passed a XMLVisitor
316 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200317 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800318 are simply called with Visit().
319
320 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200321 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800322
323 All flavors of Visit methods have a default implementation that returns 'true' (continue
324 visiting). You need to only override methods that are interesting to you.
325
Thomas Roß08bdf502012-05-12 14:21:23 +0200326 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800327
328 You should never change the document from a callback.
329
330 @sa XMLNode::Accept()
331*/
332class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800333{
334public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800335 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800336
Lee Thomason56bdd022012-02-09 18:16:58 -0800337 /// Visit a document.
338 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
339 /// Visit a document.
340 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
341
342 /// Visit an element.
343 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
344 /// Visit an element.
345 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
346
Thomas Roß08bdf502012-05-12 14:21:23 +0200347 /// Visit a declaration.
Lee Thomason50f97b22012-02-11 16:33:40 -0800348 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200349 /// Visit a text node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800350 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200351 /// Visit a comment node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800352 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200353 /// Visit an unknown node.
Lee Thomason50f97b22012-02-11 16:33:40 -0800354 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800355};
356
357
U-Stream\Leeae25a442012-02-17 17:48:16 -0800358/*
359 Utility functionality.
360*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800361class XMLUtil
362{
Lee Thomasond1983222012-02-06 08:41:24 -0800363public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800364 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
365 // correct, but simple, and usually works.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800366 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
367 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800368
369 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
370 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800371 if ( p == q ) {
372 return true;
373 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800374 while( *p && *q && *p == *q && n<nChar ) {
375 ++p; ++q; ++n;
376 }
377 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
378 return true;
379 }
380 return false;
381 }
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700382 inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800383 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
384 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800385
386 static const char* ReadBOM( const char* p, bool* hasBOM );
387 // p is the starting location,
388 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800389 static const char* GetCharacterRef( const char* p, char* value, int* length );
390 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800391};
392
Lee Thomason5cae8972012-01-24 18:03:07 -0800393
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800394/** XMLNode is a base class for every object that is in the
395 XML Document Object Model (DOM), except XMLAttributes.
396 Nodes have siblings, a parent, and children which can
397 be navigated. A node is always in a XMLDocument.
Lee Thomason3a682622012-03-25 13:19:40 -0700398 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800399 be cast to its more defined type.
400
Thomas Roß08bdf502012-05-12 14:21:23 +0200401 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800402 When the XMLDocument gets deleted, all its Nodes
403 will also be deleted.
404
405 @verbatim
406 A Document can contain: Element (container or leaf)
407 Comment (leaf)
408 Unknown (leaf)
409 Declaration( leaf )
410
411 An Element can contain: Element (container or leaf)
412 Text (leaf)
413 Attributes (not on tree)
414 Comment (leaf)
415 Unknown (leaf)
416
417 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800418*/
Lee Thomasond1983222012-02-06 08:41:24 -0800419class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800420{
421 friend class XMLDocument;
422 friend class XMLElement;
423public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800424
425 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800426 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800427 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800428 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800429
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800430 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
431 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
432 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
433 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
434 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
435 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800436
Lee Thomason50f97b22012-02-11 16:33:40 -0800437 virtual const XMLElement* ToElement() const { return 0; }
438 virtual const XMLText* ToText() const { return 0; }
439 virtual const XMLComment* ToComment() const { return 0; }
440 virtual const XMLDocument* ToDocument() const { return 0; }
441 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
442 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800443
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800444 /** The meaning of 'value' changes for the specific type.
445 @verbatim
Thomas Roß08bdf502012-05-12 14:21:23 +0200446 Document: empty
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800447 Element: name of the element
448 Comment: the comment text
449 Unknown: the tag contents
450 Text: the text string
451 @endverbatim
452 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800453 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800454 /** Set the Value of an XML node.
455 @sa Value()
456 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800457 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800458
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800459 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800460 const XMLNode* Parent() const { return parent; }
461 XMLNode* Parent() { return parent; }
462
Lee Thomason50f97b22012-02-11 16:33:40 -0800463 /// Returns true if this node has no children.
464 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800465
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800466 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800467 const XMLNode* FirstChild() const { return firstChild; }
468 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800469 /** Get the first child element, or optionally the first child
470 element with the specified name.
471 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800472 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700473 XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800474
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800475 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800476 const XMLNode* LastChild() const { return lastChild; }
477 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800478
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800479 /** Get the last child element or optionally the last child
480 element with the specified name.
481 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800482 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700483 XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800484
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800485 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800486 const XMLNode* PreviousSibling() const { return prev; }
487 XMLNode* PreviousSibling() { return prev; }
488
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800489 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800490 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason5ce89412012-03-20 13:23:44 -0700491 XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800492
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800493 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800494 const XMLNode* NextSibling() const { return next; }
495 XMLNode* NextSibling() { return next; }
496
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800497 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800498 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700499 XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800500
Lee Thomason1ff38e02012-02-14 18:18:16 -0800501 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800502 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800503 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800504 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800505
506 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800507 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800508 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800509 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800510 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800511 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800512 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800513 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800514 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
515
U-Stream\Leeae25a442012-02-17 17:48:16 -0800516 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800517 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800518 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800519 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800520
521 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800522 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800523 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800524 void DeleteChild( XMLNode* node );
525
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800526 /**
527 Make a copy of this node, but not its children.
528 You may pass in a Document pointer that will be
529 the owner of the new Node. If the 'document' is
530 null, then the node returned will be allocated
531 from the current Document. (this->GetDocument())
532
533 Note: if called on a XMLDocument, this will return null.
534 */
535 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
536
537 /**
538 Test if 2 nodes are the same, but don't test children.
539 The 2 nodes do not need to be in the same Document.
540
541 Note: if called on a XMLDocument, this will return false.
542 */
543 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
544
Thomas Roß08bdf502012-05-12 14:21:23 +0200545 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800546 XML tree will be conditionally visited and the host will be called back
547 via the TiXmlVisitor interface.
548
549 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
550 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
551 interface versus any other.)
552
553 The interface has been based on ideas from:
554
555 - http://www.saxproject.org/
556 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
557
558 Which are both good references for "visiting".
559
560 An example of using Accept():
561 @verbatim
562 TiXmlPrinter printer;
563 tinyxmlDoc.Accept( &printer );
564 const char* xmlcstr = printer.CStr();
565 @endverbatim
566 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800567 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800568
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800569 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800570 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800571
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800572protected:
573 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800574 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800575 XMLNode( const XMLNode& ); // not supported
576 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800577
Lee Thomason3f57d272012-01-11 15:30:03 -0800578 XMLDocument* document;
579 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800580 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800581
582 XMLNode* firstChild;
583 XMLNode* lastChild;
584
585 XMLNode* prev;
586 XMLNode* next;
587
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800588private:
Lee Thomasond1983222012-02-06 08:41:24 -0800589 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800590 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800591};
592
593
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800594/** XML text.
595
596 Note that a text node can have child element nodes, for example:
597 @verbatim
598 <root>This is <b>bold</b></root>
599 @endverbatim
600
601 A text node can have 2 ways to output the next. "normal" output
602 and CDATA. It will default to the mode it was parsed from the XML file and
603 you generally want to leave it alone, but you can change the output mode with
604 SetCDATA() and query it with CDATA().
605*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800606class XMLText : public XMLNode
607{
Lee Thomason2c85a712012-01-31 08:24:24 -0800608 friend class XMLBase;
609 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800610public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800611 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800612
Lee Thomason751da522012-02-10 08:50:51 -0800613 virtual XMLText* ToText() { return this; }
614 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800615
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800616 /// Declare whether this should be CDATA or standard text.
Lee Thomason5ce89412012-03-20 13:23:44 -0700617 void SetCData( bool _isCData ) { this->isCData = _isCData; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800618 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800619 bool CData() const { return isCData; }
620
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800621 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800622 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
623 virtual bool ShallowEqual( const XMLNode* compare ) const;
624
Lee Thomason5492a1c2012-01-23 15:32:10 -0800625
626protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800627 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
628 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800629 XMLText( const XMLText& ); // not supported
630 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800631
632private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800633 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800634};
635
636
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800637/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800638class XMLComment : public XMLNode
639{
Lee Thomason2c85a712012-01-31 08:24:24 -0800640 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800641public:
Lee Thomason751da522012-02-10 08:50:51 -0800642 virtual XMLComment* ToComment() { return this; }
643 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800644
Lee Thomason56bdd022012-02-09 18:16:58 -0800645 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800646
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800647 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800648 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
649 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800650
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800651protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800652 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800653 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800654 XMLComment( const XMLComment& ); // not supported
655 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800656
Lee Thomason3f57d272012-01-11 15:30:03 -0800657private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800658};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800659
660
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800661/** In correct XML the declaration is the first entry in the file.
662 @verbatim
663 <?xml version="1.0" standalone="yes"?>
664 @endverbatim
665
666 TinyXML2 will happily read or write files without a declaration,
667 however.
668
669 The text of the declaration isn't interpreted. It is parsed
670 and written as a string.
671*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800672class XMLDeclaration : public XMLNode
673{
674 friend class XMLDocument;
675public:
676 virtual XMLDeclaration* ToDeclaration() { return this; }
677 virtual const XMLDeclaration* ToDeclaration() const { return this; }
678
679 virtual bool Accept( XMLVisitor* visitor ) const;
680
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800681 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800682 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
683 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800684
685protected:
686 XMLDeclaration( XMLDocument* doc );
687 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800688 XMLDeclaration( const XMLDeclaration& ); // not supported
689 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800690};
691
692
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800693/** Any tag that tinyXml doesn't recognize is saved as an
694 unknown. It is a tag of text, but should not be modified.
695 It will be written back to the XML, unchanged, when the file
696 is saved.
697
698 DTD tags get thrown into TiXmlUnknowns.
699*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800700class XMLUnknown : public XMLNode
701{
702 friend class XMLDocument;
703public:
704 virtual XMLUnknown* ToUnknown() { return this; }
705 virtual const XMLUnknown* ToUnknown() const { return this; }
706
707 virtual bool Accept( XMLVisitor* visitor ) const;
708
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800709 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800710 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
711 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800712
713protected:
714 XMLUnknown( XMLDocument* doc );
715 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800716 XMLUnknown( const XMLUnknown& ); // not supported
717 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800718};
719
720
Lee Thomason1ff38e02012-02-14 18:18:16 -0800721enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800722 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800723 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800724
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700725 XML_NO_ATTRIBUTE,
726 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800727
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700728 XML_ERROR_FILE_NOT_FOUND,
Lee Thomason7f7b1622012-03-24 12:49:03 -0700729 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
Lee Thomasona3efec02012-06-15 14:30:44 -0700730 XML_ERROR_FILE_READ_ERROR,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700731 XML_ERROR_ELEMENT_MISMATCH,
732 XML_ERROR_PARSING_ELEMENT,
733 XML_ERROR_PARSING_ATTRIBUTE,
734 XML_ERROR_IDENTIFYING_TAG,
735 XML_ERROR_PARSING_TEXT,
736 XML_ERROR_PARSING_CDATA,
737 XML_ERROR_PARSING_COMMENT,
738 XML_ERROR_PARSING_DECLARATION,
739 XML_ERROR_PARSING_UNKNOWN,
740 XML_ERROR_EMPTY_DOCUMENT,
741 XML_ERROR_MISMATCHED_ELEMENT,
742 XML_ERROR_PARSING
Lee Thomason1ff38e02012-02-14 18:18:16 -0800743};
744
745
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800746/** An attribute is a name-value pair. Elements have an arbitrary
747 number of attributes, each with a unique name.
748
749 @note The attributes are not XMLNodes. You may only query the
750 Next() attribute in a list.
751*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800752class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800753{
754 friend class XMLElement;
755public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800756 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
757 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
758 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800759
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800760 /** IntAttribute interprets the attribute as an integer, and returns the value.
761 If the value isn't an integer, 0 will be returned. There is no error checking;
762 use QueryIntAttribute() if you need error checking.
763 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800764 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800765 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800766 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800767 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800768 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800769 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800770 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800771 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800772 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800773
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800774 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
775 in the provided paremeter. The function will return XML_NO_ERROR on success,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700776 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800777 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800778 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800779 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800780 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800781 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800782 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800783 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800784 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800785 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800786 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800787
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800788 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800789 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800790 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800791 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800792 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800793 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800794 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800795 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800796 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800797 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800798 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800799 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800800
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800801private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800802 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800803
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800804 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800805 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800806 XMLAttribute( const XMLAttribute& ); // not supported
807 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800808 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800809
Lee Thomason6f381b72012-03-02 12:59:39 -0800810 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800811
Lee Thomason751da522012-02-10 08:50:51 -0800812 mutable StrPair name;
813 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800814 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800815 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800816};
817
818
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800819/** The element is a container class. It has a value, the element name,
820 and can contain other elements, text, comments, and unknowns.
821 Elements also contain an arbitrary number of attributes.
822*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800823class XMLElement : public XMLNode
824{
Lee Thomason2c85a712012-01-31 08:24:24 -0800825 friend class XMLBase;
826 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800827public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800828 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800829 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800830 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800831 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800832
Lee Thomason751da522012-02-10 08:50:51 -0800833 virtual XMLElement* ToElement() { return this; }
834 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800835 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800836
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800837 /** Given an attribute name, Attribute() returns the value
Lee Thomason92258152012-03-24 13:05:39 -0700838 for the attribute of that name, or null if none
839 exists. For example:
840
841 @verbatim
842 const char* value = ele->Attribute( "foo" );
843 @endverbatim
844
845 The 'value' parameter is normally null. However, if specified,
846 the attribute will only be returned if the 'name' and 'value'
847 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700848
849 @verbatim
850 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
851 @endverbatim
852
853 rather than:
854 @verbatim
855 if ( ele->Attribute( "foo" ) ) {
856 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
857 }
858 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800859 */
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700860 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800861
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800862 /** Given an attribute name, IntAttribute() returns the value
863 of the attribute interpreted as an integer. 0 will be
864 returned if there is an error. For a method with error
865 checking, see QueryIntAttribute()
866 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800867 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800868 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800869 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800870 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800871 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800872 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200873 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800874 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200875 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800876
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800877 /** Given an attribute name, QueryIntAttribute() returns
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700878 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
879 can't be performed, or XML_NO_ATTRIBUTE if the attribute
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800880 doesn't exist. If successful, the result of the conversion
881 will be written to 'value'. If not successful, nothing will
882 be written to 'value'. This allows you to provide default
883 value:
884
885 @verbatim
886 int value = 10;
887 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
888 @endverbatim
889 */
Thomas Roß08bdf502012-05-12 14:21:23 +0200890 int QueryIntAttribute( const char* name, int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800891 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700892 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800893 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700894 int QueryBoolAttribute( const char* name, bool* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800895 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700896 int QueryDoubleAttribute( const char* name, double* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800897 /// See QueryIntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200898 int QueryFloatAttribute( const char* name, float* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800899
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800900 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700901 void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800902 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700903 void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800904 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700905 void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800906 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700907 void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800908 /// Sets the named attribute to value.
Thomas Roß08bdf502012-05-12 14:21:23 +0200909 void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800910
U-Stream\Leeae25a442012-02-17 17:48:16 -0800911 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800912 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800913 */
914 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800915
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800916 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800917 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800918 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800919 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800920
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800921 /** Convenience function for easy access to the text inside an element. Although easy
922 and concise, GetText() is limited compared to getting the TiXmlText child
923 and accessing it directly.
924
925 If the first child of 'this' is a TiXmlText, the GetText()
926 returns the character string of the Text node, else null is returned.
927
928 This is a convenient method for getting the text of simple contained text:
929 @verbatim
930 <foo>This is text</foo>
931 const char* str = fooElement->GetText();
932 @endverbatim
933
934 'str' will be a pointer to "This is text".
935
936 Note that this function can be misleading. If the element foo was created from
937 this XML:
938 @verbatim
939 <foo><b>This is text</b></foo>
940 @endverbatim
941
942 then the value of str would be null. The first child node isn't a text node, it is
943 another element. From this XML:
944 @verbatim
945 <foo>This is <b>text</b></foo>
946 @endverbatim
947 GetText() will return "This is ".
948 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800949 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800950
Lee Thomason2c85a712012-01-31 08:24:24 -0800951 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800952 enum {
953 OPEN, // <foo>
954 CLOSED, // <foo/>
955 CLOSING // </foo>
956 };
957 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800958 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800959 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
960 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800961
Lee Thomason50adb4c2012-02-13 15:07:09 -0800962private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800963 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800964 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800965 XMLElement( const XMLElement& ); // not supported
966 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800967
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800968 XMLAttribute* FindAttribute( const char* name );
969 XMLAttribute* FindOrCreateAttribute( const char* name );
Lee Thomason5e3803c2012-04-16 08:57:05 -0700970 //void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800971 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -0800972
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800973 int closingType;
Lee Thomason5e3803c2012-04-16 08:57:05 -0700974 // The attribute list is ordered; there is no 'lastAttribute'
975 // because the list needs to be scanned for dupes before adding
976 // a new attribute.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800977 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800978};
979
980
Thomas Roß08bdf502012-05-12 14:21:23 +0200981/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800982 It can be saved, loaded, and printed to the screen.
983 All Nodes are connected and allocated to a Document.
984 If the Document is deleted, all its Nodes are also deleted.
985*/
Lee Thomason67d61312012-01-24 16:01:51 -0800986class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800987{
Lee Thomasond1983222012-02-06 08:41:24 -0800988 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800989public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800990 /// constructor
Lee Thomason6f381b72012-03-02 12:59:39 -0800991 XMLDocument( bool processEntities = true );
Lee Thomason3f57d272012-01-11 15:30:03 -0800992 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800993
Lee Thomason751da522012-02-10 08:50:51 -0800994 virtual XMLDocument* ToDocument() { return this; }
995 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800996
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800997 /**
998 Parse an XML file from a character string.
999 Returns XML_NO_ERROR (0) on success, or
1000 an errorID.
1001 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001002 int Parse( const char* xml );
Lee Thomasond11cd162012-04-12 08:35:36 -07001003
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001004 /**
1005 Load an XML file from disk.
1006 Returns XML_NO_ERROR (0) on success, or
1007 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001008 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001009 int LoadFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001010
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001011 /**
1012 Load an XML file from disk. You are responsible
1013 for providing and closing the FILE*.
1014
1015 Returns XML_NO_ERROR (0) on success, or
1016 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001017 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001018 int LoadFile( FILE* );
Lee Thomasond11cd162012-04-12 08:35:36 -07001019
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001020 /**
1021 Save the XML file to disk.
Ken Miller81da1fb2012-04-09 23:32:26 -05001022 Returns XML_NO_ERROR (0) on success, or
1023 an errorID.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001024 */
Ken Miller81da1fb2012-04-09 23:32:26 -05001025 int SaveFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001026
Ken Miller81da1fb2012-04-09 23:32:26 -05001027 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001028 Save the XML file to disk. You are responsible
Ken Miller81da1fb2012-04-09 23:32:26 -05001029 for providing and closing the FILE*.
1030
1031 Returns XML_NO_ERROR (0) on success, or
1032 an errorID.
1033 */
1034 int SaveFile( FILE* );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001035
Lee Thomason6f381b72012-03-02 12:59:39 -08001036 bool ProcessEntities() const { return processEntities; }
1037
1038 /**
1039 Returns true if this document has a leading Byte Order Mark of UTF8.
1040 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001041 bool HasBOM() const { return writeBOM; }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001042 /** Sets whether to write the BOM when writing the file.
1043 */
1044 void SetBOM( bool useBOM ) { writeBOM = useBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001045
1046 /** Return the root element of DOM. Equivalent to FirstChildElement().
1047 To get the first node, use FirstChild().
1048 */
Lee Thomasond6277762012-02-22 16:00:12 -08001049 XMLElement* RootElement() { return FirstChildElement(); }
1050 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001051
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001052 /** Print the Document. If the Printer is not provided, it will
1053 print to stdout. If you provide Printer, this can print to a file:
1054 @verbatim
1055 XMLPrinter printer( fp );
1056 doc.Print( &printer );
1057 @endverbatim
1058
1059 Or you can use a printer to print to memory:
1060 @verbatim
1061 XMLPrinter printer;
1062 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001063 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001064 @endverbatim
1065 */
1066 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001067 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001068
Lee Thomason1ff38e02012-02-14 18:18:16 -08001069 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001070 Create a new Element associated with
1071 this Document. The memory for the Element
1072 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001073 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001074 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001075 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001076 Create a new Comment associated with
1077 this Document. The memory for the Comment
1078 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001079 */
1080 XMLComment* NewComment( const char* comment );
1081 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001082 Create a new Text associated with
1083 this Document. The memory for the Text
1084 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001085 */
1086 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001087 /**
1088 Create a new Declaration associated with
1089 this Document. The memory for the object
1090 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001091
1092 If the 'text' param is null, the standard
1093 declaration is used.:
1094 @verbatim
1095 <?xml version="1.0" encoding="UTF-8"?>
1096 @endverbatim
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001097 */
Lee Thomasonf68c4382012-04-28 14:37:11 -07001098 XMLDeclaration* NewDeclaration( const char* text=0 );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001099 /**
1100 Create a new Unknown associated with
1101 this Document. The memory for the object
1102 is managed by the Document.
1103 */
1104 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001105
U-Stream\Leeae25a442012-02-17 17:48:16 -08001106 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001107 Delete a node associated with this document.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001108 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001109 */
1110 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1111
Lee Thomason67d61312012-01-24 16:01:51 -08001112 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001113
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001114 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001115 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001116 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001117 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001118 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001119 const char* GetErrorStr1() const { return errorStr1; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001120 /// Return a possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001121 const char* GetErrorStr2() const { return errorStr2; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001122 /// If there is an error, print it to stdout.
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001123 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001124
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001125 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001126 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001127
Lee Thomason6f381b72012-03-02 12:59:39 -08001128 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
1129 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001130
Lee Thomason3f57d272012-01-11 15:30:03 -08001131private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001132 XMLDocument( const XMLDocument& ); // not supported
1133 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001134 void InitDocument();
1135
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001136 bool writeBOM;
Lee Thomason6f381b72012-03-02 12:59:39 -08001137 bool processEntities;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001138 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001139 const char* errorStr1;
1140 const char* errorStr2;
1141 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001142
1143 MemPoolT< sizeof(XMLElement) > elementPool;
1144 MemPoolT< sizeof(XMLAttribute) > attributePool;
1145 MemPoolT< sizeof(XMLText) > textPool;
1146 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001147};
1148
Lee Thomason7c913cd2012-01-26 18:32:34 -08001149
Lee Thomason3ffdd392012-03-28 17:27:55 -07001150/**
1151 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001152 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001153 DOM structure. It is a separate utility class.
1154
1155 Take an example:
1156 @verbatim
1157 <Document>
1158 <Element attributeA = "valueA">
1159 <Child attributeB = "value1" />
1160 <Child attributeB = "value2" />
1161 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001162 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001163 @endverbatim
1164
1165 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1166 easy to write a *lot* of code that looks like:
1167
1168 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001169 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001170 if ( root )
1171 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001172 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001173 if ( element )
1174 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001175 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001176 if ( child )
1177 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001178 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001179 if ( child2 )
1180 {
1181 // Finally do something useful.
1182 @endverbatim
1183
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001184 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1185 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001186 and correct to use:
1187
1188 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001189 XMLHandle docHandle( &document );
1190 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001191 if ( child2 )
1192 {
1193 // do something useful
1194 @endverbatim
1195
1196 Which is MUCH more concise and useful.
1197
1198 It is also safe to copy handles - internally they are nothing more than node pointers.
1199 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001200 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001201 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001202
1203 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001204*/
1205class XMLHandle
1206{
1207public:
1208 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Lee Thomason8b899812012-04-04 15:58:16 -07001209 XMLHandle( XMLNode* _node ) { node = _node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001210 /// Create a handle from a node.
Lee Thomason8b899812012-04-04 15:58:16 -07001211 XMLHandle( XMLNode& _node ) { node = &_node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001212 /// Copy constructor
Lee Thomason8b899812012-04-04 15:58:16 -07001213 XMLHandle( const XMLHandle& ref ) { node = ref.node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001214 /// Assignment
Lee Thomason8b899812012-04-04 15:58:16 -07001215 XMLHandle operator=( const XMLHandle& ref ) { node = ref.node; return *this; }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001216
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001217 /// Get the first child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001218 XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001219 /// Get the first child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001220 XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001221 /// Get the last child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001222 XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001223 /// Get the last child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001224 XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001225 /// Get the previous sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001226 XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001227 /// Get the previous sibling element of this handle.
Lee Thomason5708f812012-03-28 17:46:41 -07001228 XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001229 /// Get the next sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001230 XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001231 /// Get the next sibling element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001232 XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001233
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001234 /// Safe cast to XMLNode. This can return null.
Lee Thomason8b899812012-04-04 15:58:16 -07001235 XMLNode* ToNode() { return node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001236 /// Safe cast to XMLElement. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001237 XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001238 /// Safe cast to XMLText. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001239 XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001240 /// Safe cast to XMLUnknown. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001241 XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001242 /// Safe cast to XMLDeclaration. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001243 XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001244
1245private:
1246 XMLNode* node;
1247};
1248
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001249
1250/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001251 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1252 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001253*/
1254class XMLConstHandle
1255{
1256public:
1257 XMLConstHandle( const XMLNode* _node ) { node = _node; }
1258 XMLConstHandle( const XMLNode& _node ) { node = &_node; }
1259 XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; }
1260
1261 XMLConstHandle operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; }
1262
1263 const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1264 const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
1265 const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); }
1266 const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
1267 const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1268 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1269 const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1270 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1271
1272
1273 const XMLNode* ToNode() const { return node; }
1274 const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1275 const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1276 const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001277 const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1278
Lee Thomason5cae8972012-01-24 18:03:07 -08001279private:
Lee Thomason8b899812012-04-04 15:58:16 -07001280 const XMLNode* node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001281};
Lee Thomason6f381b72012-03-02 12:59:39 -08001282
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001283
1284/**
1285 Printing functionality. The XMLPrinter gives you more
1286 options than the XMLDocument::Print() method.
1287
1288 It can:
1289 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001290 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001291 -# Print XML without a XMLDocument.
1292
1293 Print to Memory
1294
1295 @verbatim
1296 XMLPrinter printer;
1297 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001298 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001299 @endverbatim
1300
1301 Print to a File
1302
1303 You provide the file pointer.
1304 @verbatim
1305 XMLPrinter printer( fp );
1306 doc.Print( &printer );
1307 @endverbatim
1308
1309 Print without a XMLDocument
1310
1311 When loading, an XML parser is very useful. However, sometimes
1312 when saving, it just gets in the way. The code is often set up
1313 for streaming, and constructing the DOM is just overhead.
1314
1315 The Printer supports the streaming case. The following code
1316 prints out a trivially simple XML file without ever creating
1317 an XML document.
1318
1319 @verbatim
1320 XMLPrinter printer( fp );
1321 printer.OpenElement( "foo" );
1322 printer.PushAttribute( "foo", "bar" );
1323 printer.CloseElement();
1324 @endverbatim
1325*/
1326class XMLPrinter : public XMLVisitor
1327{
1328public:
1329 /** Construct the printer. If the FILE* is specified,
1330 this will print to the FILE. Else it will print
Lee Thomason4cd85342012-06-04 17:02:37 -07001331 to memory, and the result is available in CStr().
1332 If 'compact' is set to true, then output is created
1333 with only required whitespace and newlines.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001334 */
sniperbat25900882012-05-28 17:22:07 +08001335 XMLPrinter( FILE* file=0, bool compact = false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001336 ~XMLPrinter() {}
1337
1338 /** If streaming, write the BOM and declaration. */
1339 void PushHeader( bool writeBOM, bool writeDeclaration );
1340 /** If streaming, start writing an element.
1341 The element must be closed with CloseElement()
1342 */
1343 void OpenElement( const char* name );
1344 /// If streaming, add an attribute to an open element.
1345 void PushAttribute( const char* name, const char* value );
1346 void PushAttribute( const char* name, int value );
1347 void PushAttribute( const char* name, unsigned value );
1348 void PushAttribute( const char* name, bool value );
1349 void PushAttribute( const char* name, double value );
1350 /// If streaming, close the Element.
1351 void CloseElement();
1352
1353 /// Add a text node.
1354 void PushText( const char* text, bool cdata=false );
Thomas Roß08bdf502012-05-12 14:21:23 +02001355 /// Add a comment.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001356 void PushComment( const char* comment );
1357
1358 void PushDeclaration( const char* value );
1359 void PushUnknown( const char* value );
1360
1361 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1362 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1363
1364 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1365 virtual bool VisitExit( const XMLElement& element );
1366
1367 virtual bool Visit( const XMLText& text );
1368 virtual bool Visit( const XMLComment& comment );
1369 virtual bool Visit( const XMLDeclaration& declaration );
1370 virtual bool Visit( const XMLUnknown& unknown );
1371
1372 /**
1373 If in print to memory mode, return a pointer to
1374 the XML file in memory.
1375 */
1376 const char* CStr() const { return buffer.Mem(); }
sniperbate01e7862012-05-21 12:45:36 +08001377 /**
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001378 If in print to memory mode, return the size
1379 of the XML file in memory. (Note the size returned
1380 includes the terminating null.)
sniperbate01e7862012-05-21 12:45:36 +08001381 */
Lee Thomasonc78dc012012-06-12 13:12:15 -07001382 int CStrSize() const { return buffer.Size(); }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001383
1384private:
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001385 void SealElement();
1386 void PrintSpace( int depth );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001387 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1388 void Print( const char* format, ... );
1389
1390 bool elementJustOpened;
1391 bool firstElement;
1392 FILE* fp;
1393 int depth;
1394 int textDepth;
1395 bool processEntities;
sniperbat25900882012-05-28 17:22:07 +08001396 bool compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001397
1398 enum {
1399 ENTITY_RANGE = 64,
1400 BUF_SIZE = 200
1401 };
1402 bool entityFlag[ENTITY_RANGE];
1403 bool restrictedEntityFlag[ENTITY_RANGE];
1404
1405 DynArray< const char*, 10 > stack;
1406 DynArray< char, 20 > buffer, accumulator;
1407};
1408
1409
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001410} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001411
1412
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001413#endif // TINYXML2_INCLUDED