blob: 93d81090e23b267ac68b6532cd264da6007c0e8b [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 Thomason2c85a712012-01-31 08:24:24 -080027
U-Lama\Lee4cee6112011-12-31 14:58:18 -080028#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -080029#include <ctype.h>
30#include <stdio.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -080031
Lee Thomason7d00b9a2012-02-27 17:54:22 -080032/*
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080033 TODO: add 'lastAttribute' for faster parsing.
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
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -080038
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080039*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080040
U-Lama\Lee4cee6112011-12-31 14:58:18 -080041#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
42 #ifndef DEBUG
43 #define DEBUG
44 #endif
45#endif
46
47
48#if defined(DEBUG)
49 #if defined(_MSC_VER)
50 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
51 #elif defined (ANDROID_NDK)
52 #include <android/log.h>
53 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
54 #else
55 #include <assert.h>
56 #define TIXMLASSERT assert
57 #endif
58#else
59 #define TIXMLASSERT( x ) {}
60#endif
61
U-Lama\Leee13c3e62011-12-28 14:36:55 -080062
Lee Thomason1a1d4a72012-02-15 09:09:25 -080063// Deprecated library function hell. Compilers want to use the
64// new safe versions. This probably doesn't fully address the problem,
65// but it gets closer. There are too many compilers for me to fully
66// test. If you get compilation troubles, undefine TIXML_SAFE
67
68#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
69 // Microsoft visual studio, version 2005 and higher.
70 #define TIXML_SNPRINTF _snprintf_s
71 #define TIXML_SSCANF sscanf_s
72#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
73 // Microsoft visual studio, version 6 and higher.
74 //#pragma message( "Using _sn* functions." )
75 #define TIXML_SNPRINTF _snprintf
76 #define TIXML_SSCANF sscanf
77#elif defined(__GNUC__) && (__GNUC__ >= 3 )
U-Stream\Leeae25a442012-02-17 17:48:16 -080078 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080079 //#warning( "Using sn* functions." )
80 #define TIXML_SNPRINTF snprintf
81 #define TIXML_SSCANF sscanf
82#else
83 #define TIXML_SNPRINTF snprintf
84 #define TIXML_SSCANF sscanf
85#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080086
Lee Thomason27057312012-03-02 09:04:53 -080087static const int TIXML2_MAJOR_VERSION = 0;
88static const int TIXML2_MINOR_VERSION = 9;
89static const int TIXML2_PATCH_VERSION = 0;
Lee Thomason1ff38e02012-02-14 18:18:16 -080090
U-Lama\Leee13c3e62011-12-28 14:36:55 -080091namespace tinyxml2
92{
Lee Thomasonce0763e2012-01-11 15:43:54 -080093class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080094class XMLElement;
95class XMLAttribute;
96class XMLComment;
97class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080098class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080099class XMLDeclaration;
100class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800101
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800102class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800103
U-Stream\Leeae25a442012-02-17 17:48:16 -0800104/*
105 A class that wraps strings. Normally stores the start and end
106 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800107 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800108 manage) a traditional char[]
109*/
Lee Thomason39ede242012-01-20 11:27:56 -0800110class StrPair
111{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800112public:
Lee Thomason39ede242012-01-20 11:27:56 -0800113 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800114 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800115 NEEDS_NEWLINE_NORMALIZATION = 0x02,
116
117 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800118 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800119 ATTRIBUTE_NAME = 0,
120 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800121 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800122 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -0800123 };
124
125 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800126 ~StrPair();
127
Lee Thomasone4422302012-01-20 17:59:50 -0800128 void Set( char* start, char* end, int flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800129 Reset();
Lee Thomason39ede242012-01-20 11:27:56 -0800130 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
131 }
132 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800133 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800134
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800135 void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; }
136 void SetStr( const char* str, int flags=0 );
137
Lee Thomason56bdd022012-02-09 18:16:58 -0800138 char* ParseText( char* in, const char* endTag, int strFlags );
139 char* ParseName( char* in );
140
Lee Thomason2c85a712012-01-31 08:24:24 -0800141
Lee Thomason39ede242012-01-20 11:27:56 -0800142private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800143 void Reset();
144
Lee Thomasone4422302012-01-20 17:59:50 -0800145 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800146 NEEDS_FLUSH = 0x100,
147 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800148 };
149
Lee Thomason39ede242012-01-20 11:27:56 -0800150 // After parsing, if *end != 0, it can be set to zero.
151 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800152 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800153 char* end;
154};
155
U-Lama\Lee560bd472011-12-28 19:42:49 -0800156
U-Stream\Leeae25a442012-02-17 17:48:16 -0800157/*
158 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
159 Has a small initial memory pool, so that low or no usage will not
160 cause a call to new/delete
161*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800162template <class T, int INIT>
163class DynArray
164{
165public:
166 DynArray< T, INIT >()
167 {
168 mem = pool;
169 allocated = INIT;
170 size = 0;
171 }
172 ~DynArray()
173 {
174 if ( mem != pool ) {
175 delete mem;
176 }
177 }
178 void Push( T t )
179 {
180 EnsureCapacity( size+1 );
181 mem[size++] = t;
182 }
183
184 T* PushArr( int count )
185 {
186 EnsureCapacity( size+count );
187 T* ret = &mem[size];
188 size += count;
189 return ret;
190 }
191 T Pop() {
192 return mem[--size];
193 }
194 void PopArr( int count )
195 {
196 TIXMLASSERT( size >= count );
197 size -= count;
198 }
199
U-Stream\Leeae25a442012-02-17 17:48:16 -0800200 bool Empty() const { return size == 0; }
201 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
202 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
203 int Size() const { return size; }
204 int Capacity() const { return allocated; }
205 const T* Mem() const { return mem; }
206 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
208
209private:
210 void EnsureCapacity( int cap ) {
211 if ( cap > allocated ) {
212 int newAllocated = cap * 2;
213 T* newMem = new T[newAllocated];
214 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
215 if ( mem != pool ) delete [] mem;
216 mem = newMem;
217 allocated = newAllocated;
218 }
219 }
220
221 T* mem;
222 T pool[INIT];
223 int allocated; // objects allocated
224 int size; // number objects in use
225};
226
Lee Thomason50adb4c2012-02-13 15:07:09 -0800227
U-Stream\Leeae25a442012-02-17 17:48:16 -0800228/*
229 Parent virtual class a a pool for fast allocation
230 and deallocation of objects.
231*/
Lee Thomasond1983222012-02-06 08:41:24 -0800232class MemPool
233{
234public:
235 MemPool() {}
236 virtual ~MemPool() {}
237
238 virtual int ItemSize() const = 0;
239 virtual void* Alloc() = 0;
240 virtual void Free( void* ) = 0;
241};
242
Lee Thomason50adb4c2012-02-13 15:07:09 -0800243
U-Stream\Leeae25a442012-02-17 17:48:16 -0800244/*
245 Template child class to create pools of the correct type.
246*/
Lee Thomasond1983222012-02-06 08:41:24 -0800247template< int SIZE >
248class MemPoolT : public MemPool
249{
250public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800251 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800252 ~MemPoolT() {
253 // Delete the blocks.
254 for( int i=0; i<blockPtrs.Size(); ++i ) {
255 delete blockPtrs[i];
256 }
257 }
258
259 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800260 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800261
262 virtual void* Alloc() {
263 if ( !root ) {
264 // Need a new block.
265 Block* block = new Block();
266 blockPtrs.Push( block );
267
268 for( int i=0; i<COUNT-1; ++i ) {
269 block->chunk[i].next = &block->chunk[i+1];
270 }
271 block->chunk[COUNT-1].next = 0;
272 root = block->chunk;
273 }
274 void* result = root;
275 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800276
277 ++currentAllocs;
278 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
279 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800280 return result;
281 }
282 virtual void Free( void* mem ) {
283 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800284 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800285 Chunk* chunk = (Chunk*)mem;
286 memset( chunk, 0xfe, sizeof(Chunk) );
287 chunk->next = root;
288 root = chunk;
289 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800290 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800291 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
292 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800293 }
Lee Thomasond1983222012-02-06 08:41:24 -0800294
295private:
296 enum { COUNT = 1024/SIZE };
297 union Chunk {
298 Chunk* next;
299 char mem[SIZE];
300 };
301 struct Block {
302 Chunk chunk[COUNT];
303 };
304 DynArray< Block*, 10 > blockPtrs;
305 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800306
307 int currentAllocs;
308 int nAllocs;
309 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800310};
311
Lee Thomason2c85a712012-01-31 08:24:24 -0800312
Lee Thomason56bdd022012-02-09 18:16:58 -0800313
314/**
315 Implements the interface to the "Visitor pattern" (see the Accept() method.)
316 If you call the Accept() method, it requires being passed a XMLVisitor
317 class to handle callbacks. For nodes that contain other nodes (Document, Element)
318 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
319 are simply called with Visit().
320
321 If you return 'true' from a Visit method, recursive parsing will continue. If you return
322 false, <b>no children of this node or its sibilings</b> will be Visited.
323
324 All flavors of Visit methods have a default implementation that returns 'true' (continue
325 visiting). You need to only override methods that are interesting to you.
326
327 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
328
329 You should never change the document from a callback.
330
331 @sa XMLNode::Accept()
332*/
333class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800334{
335public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800336 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800337
Lee Thomason56bdd022012-02-09 18:16:58 -0800338 /// Visit a document.
339 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
340 /// Visit a document.
341 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
342
343 /// Visit an element.
344 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
345 /// Visit an element.
346 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
347
348 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800349 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800350 /// Visit a text node
351 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
352 /// Visit a comment node
353 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
354 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800355 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800356};
357
358
U-Stream\Leeae25a442012-02-17 17:48:16 -0800359/*
360 Utility functionality.
361*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800362class XMLUtil
363{
Lee Thomasond1983222012-02-06 08:41:24 -0800364public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800365 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
366 // correct, but simple, and usually works.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800367 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
368 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800369
370 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
371 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800372 if ( p == q ) {
373 return true;
374 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800375 while( *p && *q && *p == *q && n<nChar ) {
376 ++p; ++q; ++n;
377 }
378 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
379 return true;
380 }
381 return false;
382 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800383 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800384 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
385 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800386
387 static const char* ReadBOM( const char* p, bool* hasBOM );
388 // p is the starting location,
389 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800390 static const char* GetCharacterRef( const char* p, char* value, int* length );
391 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800392};
393
Lee Thomason5cae8972012-01-24 18:03:07 -0800394
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800395/** XMLNode is a base class for every object that is in the
396 XML Document Object Model (DOM), except XMLAttributes.
397 Nodes have siblings, a parent, and children which can
398 be navigated. A node is always in a XMLDocument.
399 The type of a TiXmlNode can be queried, and it can
400 be cast to its more defined type.
401
402 An XMLDocument allocates memory for all its Nodes.
403 When the XMLDocument gets deleted, all its Nodes
404 will also be deleted.
405
406 @verbatim
407 A Document can contain: Element (container or leaf)
408 Comment (leaf)
409 Unknown (leaf)
410 Declaration( leaf )
411
412 An Element can contain: Element (container or leaf)
413 Text (leaf)
414 Attributes (not on tree)
415 Comment (leaf)
416 Unknown (leaf)
417
418 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800419*/
Lee Thomasond1983222012-02-06 08:41:24 -0800420class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800421{
422 friend class XMLDocument;
423 friend class XMLElement;
424public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800425
426 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800427 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800428 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800429 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800430
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800431 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
432 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
433 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
434 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
435 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
436 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800437
Lee Thomason50f97b22012-02-11 16:33:40 -0800438 virtual const XMLElement* ToElement() const { return 0; }
439 virtual const XMLText* ToText() const { return 0; }
440 virtual const XMLComment* ToComment() const { return 0; }
441 virtual const XMLDocument* ToDocument() const { return 0; }
442 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
443 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800444
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800445 /** The meaning of 'value' changes for the specific type.
446 @verbatim
447 Document: empy
448 Element: name of the element
449 Comment: the comment text
450 Unknown: the tag contents
451 Text: the text string
452 @endverbatim
453 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800454 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800455 /** Set the Value of an XML node.
456 @sa Value()
457 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800458 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800459
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800460 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800461 const XMLNode* Parent() const { return parent; }
462 XMLNode* Parent() { return parent; }
463
Lee Thomason50f97b22012-02-11 16:33:40 -0800464 /// Returns true if this node has no children.
465 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800466
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800467 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800468 const XMLNode* FirstChild() const { return firstChild; }
469 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800470 /** Get the first child element, or optionally the first child
471 element with the specified name.
472 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800473 const XMLElement* FirstChildElement( const char* value=0 ) const;
474 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800475
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800476 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800477 const XMLNode* LastChild() const { return lastChild; }
478 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800479
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800480 /** Get the last child element or optionally the last child
481 element with the specified name.
482 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800483 const XMLElement* LastChildElement( const char* value=0 ) const;
484 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
485
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800486 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800487 const XMLNode* PreviousSibling() const { return prev; }
488 XMLNode* PreviousSibling() { return prev; }
489
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800490 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800491 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
492 XMLElement* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800493
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800494 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800495 const XMLNode* NextSibling() const { return next; }
496 XMLNode* NextSibling() { return next; }
497
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800498 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800499 const XMLElement* NextSiblingElement( const char* value=0 ) const;
500 XMLElement* NextSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800501
Lee Thomason1ff38e02012-02-14 18:18:16 -0800502 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800503 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800504 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800505 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800506
507 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800508 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800509 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800510 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800511 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800512 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800513 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800514 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800515 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
516
U-Stream\Leeae25a442012-02-17 17:48:16 -0800517 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800518 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800519 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800520 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800521
522 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800523 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800524 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800525 void DeleteChild( XMLNode* node );
526
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800527 /**
528 Make a copy of this node, but not its children.
529 You may pass in a Document pointer that will be
530 the owner of the new Node. If the 'document' is
531 null, then the node returned will be allocated
532 from the current Document. (this->GetDocument())
533
534 Note: if called on a XMLDocument, this will return null.
535 */
536 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
537
538 /**
539 Test if 2 nodes are the same, but don't test children.
540 The 2 nodes do not need to be in the same Document.
541
542 Note: if called on a XMLDocument, this will return false.
543 */
544 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
545
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800546 /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
547 XML tree will be conditionally visited and the host will be called back
548 via the TiXmlVisitor interface.
549
550 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
551 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
552 interface versus any other.)
553
554 The interface has been based on ideas from:
555
556 - http://www.saxproject.org/
557 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
558
559 Which are both good references for "visiting".
560
561 An example of using Accept():
562 @verbatim
563 TiXmlPrinter printer;
564 tinyxmlDoc.Accept( &printer );
565 const char* xmlcstr = printer.CStr();
566 @endverbatim
567 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800568 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800569
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800570 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800571 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800572
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800573protected:
574 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800575 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800576 XMLNode( const XMLNode& ); // not supported
577 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800578
Lee Thomason3f57d272012-01-11 15:30:03 -0800579 XMLDocument* document;
580 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800581 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800582
583 XMLNode* firstChild;
584 XMLNode* lastChild;
585
586 XMLNode* prev;
587 XMLNode* next;
588
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800589private:
Lee Thomasond1983222012-02-06 08:41:24 -0800590 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800591 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800592};
593
594
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800595/** XML text.
596
597 Note that a text node can have child element nodes, for example:
598 @verbatim
599 <root>This is <b>bold</b></root>
600 @endverbatim
601
602 A text node can have 2 ways to output the next. "normal" output
603 and CDATA. It will default to the mode it was parsed from the XML file and
604 you generally want to leave it alone, but you can change the output mode with
605 SetCDATA() and query it with CDATA().
606*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800607class XMLText : public XMLNode
608{
Lee Thomason2c85a712012-01-31 08:24:24 -0800609 friend class XMLBase;
610 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800611public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800612 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800613
Lee Thomason751da522012-02-10 08:50:51 -0800614 virtual XMLText* ToText() { return this; }
615 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800616
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800617 /// Declare whether this should be CDATA or standard text.
618 void SetCData( bool isCData ) { this->isCData = isCData; }
619 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800620 bool CData() const { return isCData; }
621
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800622 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800623 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
624 virtual bool ShallowEqual( const XMLNode* compare ) const;
625
Lee Thomason5492a1c2012-01-23 15:32:10 -0800626
627protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800628 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
629 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800630 XMLText( const XMLText& ); // not supported
631 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800632
633private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800634 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800635};
636
637
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800638/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800639class XMLComment : public XMLNode
640{
Lee Thomason2c85a712012-01-31 08:24:24 -0800641 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800642public:
Lee Thomason751da522012-02-10 08:50:51 -0800643 virtual XMLComment* ToComment() { return this; }
644 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800645
Lee Thomason56bdd022012-02-09 18:16:58 -0800646 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800647
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800648 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800649 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
650 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800651
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800652protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800653 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800654 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800655 XMLComment( const XMLComment& ); // not supported
656 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800657
Lee Thomason3f57d272012-01-11 15:30:03 -0800658private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800659};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800660
661
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800662/** In correct XML the declaration is the first entry in the file.
663 @verbatim
664 <?xml version="1.0" standalone="yes"?>
665 @endverbatim
666
667 TinyXML2 will happily read or write files without a declaration,
668 however.
669
670 The text of the declaration isn't interpreted. It is parsed
671 and written as a string.
672*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800673class XMLDeclaration : public XMLNode
674{
675 friend class XMLDocument;
676public:
677 virtual XMLDeclaration* ToDeclaration() { return this; }
678 virtual const XMLDeclaration* ToDeclaration() const { return this; }
679
680 virtual bool Accept( XMLVisitor* visitor ) const;
681
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800682 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800683 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
684 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800685
686protected:
687 XMLDeclaration( XMLDocument* doc );
688 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800689 XMLDeclaration( const XMLDeclaration& ); // not supported
690 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800691};
692
693
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800694/** Any tag that tinyXml doesn't recognize is saved as an
695 unknown. It is a tag of text, but should not be modified.
696 It will be written back to the XML, unchanged, when the file
697 is saved.
698
699 DTD tags get thrown into TiXmlUnknowns.
700*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800701class XMLUnknown : public XMLNode
702{
703 friend class XMLDocument;
704public:
705 virtual XMLUnknown* ToUnknown() { return this; }
706 virtual const XMLUnknown* ToUnknown() const { return this; }
707
708 virtual bool Accept( XMLVisitor* visitor ) const;
709
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800710 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800711 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
712 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800713
714protected:
715 XMLUnknown( XMLDocument* doc );
716 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800717 XMLUnknown( const XMLUnknown& ); // not supported
718 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800719};
720
721
Lee Thomason1ff38e02012-02-14 18:18:16 -0800722enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800723 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800724 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800725
Lee Thomason1ff38e02012-02-14 18:18:16 -0800726 NO_ATTRIBUTE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800727 WRONG_ATTRIBUTE_TYPE,
728
729 ERROR_FILE_NOT_FOUND,
730 ERROR_ELEMENT_MISMATCH,
731 ERROR_PARSING_ELEMENT,
732 ERROR_PARSING_ATTRIBUTE,
733 ERROR_IDENTIFYING_TAG,
734 ERROR_PARSING_TEXT,
735 ERROR_PARSING_CDATA,
736 ERROR_PARSING_COMMENT,
737 ERROR_PARSING_DECLARATION,
Lee Thomasond6277762012-02-22 16:00:12 -0800738 ERROR_PARSING_UNKNOWN,
739 ERROR_EMPTY_DOCUMENT,
Lee Thomason (grinliz)784607f2012-02-24 16:23:40 -0800740 ERROR_MISMATCHED_ELEMENT,
741 ERROR_PARSING
Lee Thomason1ff38e02012-02-14 18:18:16 -0800742};
743
744
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800745/** An attribute is a name-value pair. Elements have an arbitrary
746 number of attributes, each with a unique name.
747
748 @note The attributes are not XMLNodes. You may only query the
749 Next() attribute in a list.
750*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800751class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800752{
753 friend class XMLElement;
754public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800755 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
756 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
757 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800758
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800759 /** IntAttribute interprets the attribute as an integer, and returns the value.
760 If the value isn't an integer, 0 will be returned. There is no error checking;
761 use QueryIntAttribute() if you need error checking.
762 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800763 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800764 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800765 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800766 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800767 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800768 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800769 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800770 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800771 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800772
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800773 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
774 in the provided paremeter. The function will return XML_NO_ERROR on success,
775 and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
776 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800777 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800778 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800779 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800780 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800781 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800782 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800783 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800784 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800785 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800786
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800787 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800788 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800789 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800790 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800791 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800792 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800793 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800794 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800795 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800796 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800797 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800798 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800799
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800800private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800801 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800802
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800803 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800804 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800805 XMLAttribute( const XMLAttribute& ); // not supported
806 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800807 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800808
Lee Thomason6f381b72012-03-02 12:59:39 -0800809 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800810
Lee Thomason751da522012-02-10 08:50:51 -0800811 mutable StrPair name;
812 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800813 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800814 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800815};
816
817
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800818/** The element is a container class. It has a value, the element name,
819 and can contain other elements, text, comments, and unknowns.
820 Elements also contain an arbitrary number of attributes.
821*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800822class XMLElement : public XMLNode
823{
Lee Thomason2c85a712012-01-31 08:24:24 -0800824 friend class XMLBase;
825 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800826public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800827 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800828 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800829 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800830 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800831
Lee Thomason751da522012-02-10 08:50:51 -0800832 virtual XMLElement* ToElement() { return this; }
833 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800834 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800835
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800836 /** Given an attribute name, Attribute() returns the value
837 for the attribute of that name, or null if none exists.
838 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800839 const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); }
Lee Thomason751da522012-02-10 08:50:51 -0800840
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800841 /** Given an attribute name, IntAttribute() returns the value
842 of the attribute interpreted as an integer. 0 will be
843 returned if there is an error. For a method with error
844 checking, see QueryIntAttribute()
845 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800846 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800847 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800848 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800849 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800850 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800851 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800852 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800853 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800854 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
855
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800856 /** Given an attribute name, QueryIntAttribute() returns
857 XML_NO_ERROR, WRONG_ATTRIBUTE_TYPE if the conversion
858 can't be performed, or NO_ATTRIBUTE if the attribute
859 doesn't exist. If successful, the result of the conversion
860 will be written to 'value'. If not successful, nothing will
861 be written to 'value'. This allows you to provide default
862 value:
863
864 @verbatim
865 int value = 10;
866 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
867 @endverbatim
868 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800869 int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800870 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800871 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800872 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800873 int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800874 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800875 int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800876 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800877 int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatValue( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800878
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800879 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800880 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800881 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800882 void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800883 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800884 void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800885 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800886 void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800887 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800888 void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800889
U-Stream\Leeae25a442012-02-17 17:48:16 -0800890 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800891 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800892 */
893 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800894
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800895 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800896 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800897 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800898 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800899
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800900 /** Convenience function for easy access to the text inside an element. Although easy
901 and concise, GetText() is limited compared to getting the TiXmlText child
902 and accessing it directly.
903
904 If the first child of 'this' is a TiXmlText, the GetText()
905 returns the character string of the Text node, else null is returned.
906
907 This is a convenient method for getting the text of simple contained text:
908 @verbatim
909 <foo>This is text</foo>
910 const char* str = fooElement->GetText();
911 @endverbatim
912
913 'str' will be a pointer to "This is text".
914
915 Note that this function can be misleading. If the element foo was created from
916 this XML:
917 @verbatim
918 <foo><b>This is text</b></foo>
919 @endverbatim
920
921 then the value of str would be null. The first child node isn't a text node, it is
922 another element. From this XML:
923 @verbatim
924 <foo>This is <b>text</b></foo>
925 @endverbatim
926 GetText() will return "This is ".
927 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800928 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800929
Lee Thomason2c85a712012-01-31 08:24:24 -0800930 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800931 enum {
932 OPEN, // <foo>
933 CLOSED, // <foo/>
934 CLOSING // </foo>
935 };
936 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800937 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800938 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
939 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800940
Lee Thomason50adb4c2012-02-13 15:07:09 -0800941private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800942 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800943 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800944 XMLElement( const XMLElement& ); // not supported
945 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800946
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800947 XMLAttribute* FindAttribute( const char* name );
948 XMLAttribute* FindOrCreateAttribute( const char* name );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800949 void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800950 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -0800951
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800952 int closingType;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800953 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800954};
955
956
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800957/** A document binds together all the functionality.
958 It can be saved, loaded, and printed to the screen.
959 All Nodes are connected and allocated to a Document.
960 If the Document is deleted, all its Nodes are also deleted.
961*/
Lee Thomason67d61312012-01-24 16:01:51 -0800962class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800963{
Lee Thomasond1983222012-02-06 08:41:24 -0800964 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800965public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800966 /// constructor
Lee Thomason6f381b72012-03-02 12:59:39 -0800967 XMLDocument( bool processEntities = true );
Lee Thomason3f57d272012-01-11 15:30:03 -0800968 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800969
Lee Thomason751da522012-02-10 08:50:51 -0800970 virtual XMLDocument* ToDocument() { return this; }
971 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800972
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800973 /**
974 Parse an XML file from a character string.
975 Returns XML_NO_ERROR (0) on success, or
976 an errorID.
977 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800978 int Parse( const char* xml );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800979 /**
980 Load an XML file from disk.
981 Returns XML_NO_ERROR (0) on success, or
982 an errorID.
983 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800984 int LoadFile( const char* filename );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800985 /**
986 Load an XML file from disk. You are responsible
987 for providing and closing the FILE*.
988
989 Returns XML_NO_ERROR (0) on success, or
990 an errorID.
991 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800992 int LoadFile( FILE* );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800993 /**
994 Save the XML file to disk.
995 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800996 void SaveFile( const char* filename );
997
Lee Thomason6f381b72012-03-02 12:59:39 -0800998 bool ProcessEntities() const { return processEntities; }
999
1000 /**
1001 Returns true if this document has a leading Byte Order Mark of UTF8.
1002 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001003 bool HasBOM() const { return writeBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001004
1005 /** Return the root element of DOM. Equivalent to FirstChildElement().
1006 To get the first node, use FirstChild().
1007 */
Lee Thomasond6277762012-02-22 16:00:12 -08001008 XMLElement* RootElement() { return FirstChildElement(); }
1009 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001010
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001011 /** Print the Document. If the Printer is not provided, it will
1012 print to stdout. If you provide Printer, this can print to a file:
1013 @verbatim
1014 XMLPrinter printer( fp );
1015 doc.Print( &printer );
1016 @endverbatim
1017
1018 Or you can use a printer to print to memory:
1019 @verbatim
1020 XMLPrinter printer;
1021 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001022 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001023 @endverbatim
1024 */
1025 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001026 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001027
Lee Thomason1ff38e02012-02-14 18:18:16 -08001028 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001029 Create a new Element associated with
1030 this Document. The memory for the Element
1031 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001032 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001033 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001034 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001035 Create a new Comment associated with
1036 this Document. The memory for the Comment
1037 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001038 */
1039 XMLComment* NewComment( const char* comment );
1040 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001041 Create a new Text associated with
1042 this Document. The memory for the Text
1043 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001044 */
1045 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001046 /**
1047 Create a new Declaration associated with
1048 this Document. The memory for the object
1049 is managed by the Document.
1050 */
1051 XMLDeclaration* NewDeclaration( const char* text );
1052 /**
1053 Create a new Unknown associated with
1054 this Document. The memory for the object
1055 is managed by the Document.
1056 */
1057 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001058
U-Stream\Leeae25a442012-02-17 17:48:16 -08001059 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001060 Delete a node associated with this documented.
1061 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001062 */
1063 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1064
Lee Thomason67d61312012-01-24 16:01:51 -08001065 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001066
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001067 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001068 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001069 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001070 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001071 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001072 const char* GetErrorStr1() const { return errorStr1; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001073 /// Return possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001074 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001075 /// If there is an error, print it to stdout
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001076 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001077
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001078 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001079 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001080
Lee Thomason6f381b72012-03-02 12:59:39 -08001081 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
1082 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001083
Lee Thomason3f57d272012-01-11 15:30:03 -08001084private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001085 XMLDocument( const XMLDocument& ); // not supported
1086 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001087 void InitDocument();
1088
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001089 bool writeBOM;
Lee Thomason6f381b72012-03-02 12:59:39 -08001090 bool processEntities;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001091 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001092 const char* errorStr1;
1093 const char* errorStr2;
1094 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001095
1096 MemPoolT< sizeof(XMLElement) > elementPool;
1097 MemPoolT< sizeof(XMLAttribute) > attributePool;
1098 MemPoolT< sizeof(XMLText) > textPool;
1099 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001100};
1101
Lee Thomason7c913cd2012-01-26 18:32:34 -08001102
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001103
1104/**
1105 Printing functionality. The XMLPrinter gives you more
1106 options than the XMLDocument::Print() method.
1107
1108 It can:
1109 -# Print to memory.
1110 -# Print to a file you provide
1111 -# Print XML without a XMLDocument.
1112
1113 Print to Memory
1114
1115 @verbatim
1116 XMLPrinter printer;
1117 doc->Print( &printer );
1118 SomeFunctior( printer.CStr() );
1119 @endverbatim
1120
1121 Print to a File
1122
1123 You provide the file pointer.
1124 @verbatim
1125 XMLPrinter printer( fp );
1126 doc.Print( &printer );
1127 @endverbatim
1128
1129 Print without a XMLDocument
1130
1131 When loading, an XML parser is very useful. However, sometimes
1132 when saving, it just gets in the way. The code is often set up
1133 for streaming, and constructing the DOM is just overhead.
1134
1135 The Printer supports the streaming case. The following code
1136 prints out a trivially simple XML file without ever creating
1137 an XML document.
1138
1139 @verbatim
1140 XMLPrinter printer( fp );
1141 printer.OpenElement( "foo" );
1142 printer.PushAttribute( "foo", "bar" );
1143 printer.CloseElement();
1144 @endverbatim
1145*/
1146class XMLPrinter : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -08001147{
1148public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001149 /** Construct the printer. If the FILE* is specified,
1150 this will print to the FILE. Else it will print
1151 to memory, and the result is available in CStr()
1152 */
1153 XMLPrinter( FILE* file=0 );
1154 ~XMLPrinter() {}
Lee Thomason5cae8972012-01-24 18:03:07 -08001155
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001156 /** If streaming, write the BOM and declaration. */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001157 void PushHeader( bool writeBOM, bool writeDeclaration );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001158 /** If streaming, start writing an element.
1159 The element must be closed with CloseElement()
1160 */
Lee Thomason56bdd022012-02-09 18:16:58 -08001161 void OpenElement( const char* name );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001162 /// If streaming, add an attribute to an open element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001163 void PushAttribute( const char* name, const char* value );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001164 void PushAttribute( const char* name, int value );
1165 void PushAttribute( const char* name, unsigned value );
1166 void PushAttribute( const char* name, bool value );
1167 void PushAttribute( const char* name, double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001168 /// If streaming, close the Element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001169 void CloseElement();
1170
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001171 /// Add a text node.
Lee Thomason50f97b22012-02-11 16:33:40 -08001172 void PushText( const char* text, bool cdata=false );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001173 /// Add a comment
Lee Thomason5cae8972012-01-24 18:03:07 -08001174 void PushComment( const char* comment );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001175
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001176 void PushDeclaration( const char* value );
1177 void PushUnknown( const char* value );
Lee Thomason5cae8972012-01-24 18:03:07 -08001178
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001179 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
Lee Thomason751da522012-02-10 08:50:51 -08001180 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1181
1182 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1183 virtual bool VisitExit( const XMLElement& element );
1184
1185 virtual bool Visit( const XMLText& text );
1186 virtual bool Visit( const XMLComment& comment );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001187 virtual bool Visit( const XMLDeclaration& declaration );
1188 virtual bool Visit( const XMLUnknown& unknown );
Lee Thomason751da522012-02-10 08:50:51 -08001189
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001190 /**
1191 If in print to memory mode, return a pointer to
1192 the XML file in memory.
1193 */
U-Stream\Leeae25a442012-02-17 17:48:16 -08001194 const char* CStr() const { return buffer.Mem(); }
Lee Thomason751da522012-02-10 08:50:51 -08001195
Lee Thomason5cae8972012-01-24 18:03:07 -08001196private:
1197 void SealElement();
1198 void PrintSpace( int depth );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001199 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001200 void Print( const char* format, ... );
Lee Thomason5cae8972012-01-24 18:03:07 -08001201
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001202 bool elementJustOpened;
1203 bool firstElement;
Lee Thomason5cae8972012-01-24 18:03:07 -08001204 FILE* fp;
1205 int depth;
Lee Thomason56bdd022012-02-09 18:16:58 -08001206 int textDepth;
Lee Thomason6f381b72012-03-02 12:59:39 -08001207 bool processEntities;
Lee Thomason56bdd022012-02-09 18:16:58 -08001208
Lee Thomason857b8682012-01-25 17:50:25 -08001209 enum {
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001210 ENTITY_RANGE = 64,
1211 BUF_SIZE = 200
Lee Thomason857b8682012-01-25 17:50:25 -08001212 };
1213 bool entityFlag[ENTITY_RANGE];
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001214 bool restrictedEntityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -08001215
Lee Thomason2c85a712012-01-31 08:24:24 -08001216 DynArray< const char*, 10 > stack;
U-Stream\Leeae25a442012-02-17 17:48:16 -08001217 DynArray< char, 20 > buffer, accumulator;
Lee Thomason5cae8972012-01-24 18:03:07 -08001218};
1219
1220
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001221}; // tinyxml2
1222
U-Lama\Lee560bd472011-12-28 19:42:49 -08001223
1224
U-Stream\Leeae25a442012-02-17 17:48:16 -08001225#endif // TINYXML2_INCLUDED