blob: 92e2b574596d8a41652db711cc23741355c997f1 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070027#ifdef ANDROID_NDK
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
48 g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
49
50 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# if defined(_MSC_VER)
63# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64# elif defined (ANDROID_NDK)
65# include <android/log.h>
66# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67# else
68# include <assert.h>
69# define TIXMLASSERT assert
70# endif
71# else
72# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// Microsoft visual studio, version 2005 and higher.
78/*int _snprintf_s(
79 char *buffer,
80 size_t sizeOfBuffer,
81 size_t count,
82 const char *format [,
83 argument] ...
84);*/
85inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86{
87 va_list va;
88 va_start( va, format );
89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90 va_end( va );
91 return result;
92}
93#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700103static const int TIXML2_PATCH_VERSION = 8;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
111class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800112class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800113class XMLDeclaration;
114class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800115
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118/*
119 A class that wraps strings. Normally stores the start and end
120 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800121 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800122 manage) a traditional char[]
123*/
Lee Thomason39ede242012-01-20 11:27:56 -0800124class StrPair
125{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700127 enum {
128 NEEDS_ENTITY_PROCESSING = 0x01,
129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
Lee Thomason624d43f2012-10-12 10:58:48 -0700132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason624d43f2012-10-12 10:58:48 -0700134 ATTRIBUTE_NAME = 0,
135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700138 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 // After parsing, if *end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 int _flags;
177 char* _start;
178 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800187template <class T, int INIT>
188class DynArray
189{
190public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700192 _mem = _pool;
193 _allocated = INIT;
194 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700204 EnsureCapacity( _size+1 );
205 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700206 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 EnsureCapacity( _size+count );
210 T* ret = &_mem[_size];
211 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 return ret;
213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 TIXMLASSERT( _size >= count );
221 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700230 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700235 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800253
Lee Thomason2c85a712012-01-31 08:24:24 -0800254private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int newAllocated = cap * 2;
258 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
260 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700261 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
266 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800267
Lee Thomason624d43f2012-10-12 10:58:48 -0700268 T* _mem;
269 T _pool[INIT];
270 int _allocated; // objects allocated
271 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800272};
273
Lee Thomason50adb4c2012-02-13 15:07:09 -0800274
U-Stream\Leeae25a442012-02-17 17:48:16 -0800275/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200276 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800277 and deallocation of objects.
278*/
Lee Thomasond1983222012-02-06 08:41:24 -0800279class MemPool
280{
281public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 MemPool() {}
283 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800284
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 virtual int ItemSize() const = 0;
286 virtual void* Alloc() = 0;
287 virtual void Free( void* ) = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800288};
289
Lee Thomason50adb4c2012-02-13 15:07:09 -0800290
U-Stream\Leeae25a442012-02-17 17:48:16 -0800291/*
292 Template child class to create pools of the correct type.
293*/
Lee Thomasond1983222012-02-06 08:41:24 -0800294template< int SIZE >
295class MemPoolT : public MemPool
296{
297public:
Lee Thomason624d43f2012-10-12 10:58:48 -0700298 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700299 ~MemPoolT() {
300 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700301 for( int i=0; i<_blockPtrs.Size(); ++i ) {
302 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 }
304 }
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const {
307 return SIZE;
308 }
309 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700310 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700311 }
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700314 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700315 // Need a new block.
316 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700317 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800318
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700319 for( int i=0; i<COUNT-1; ++i ) {
320 block->chunk[i].next = &block->chunk[i+1];
321 }
322 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700325 void* result = _root;
326 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800327
Lee Thomason624d43f2012-10-12 10:58:48 -0700328 ++_currentAllocs;
329 if ( _currentAllocs > _maxAllocs ) {
330 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 _nAllocs++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 return result;
334 }
335 virtual void Free( void* mem ) {
336 if ( !mem ) {
337 return;
338 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700341#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 chunk->next = _root;
345 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
347 void Trace( const char* name ) {
348 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700350 }
Lee Thomasond1983222012-02-06 08:41:24 -0800351
352private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 enum { COUNT = 1024/SIZE };
354 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700355 Chunk* next;
356 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700357 };
358 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700359 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700361 DynArray< Block*, 10 > _blockPtrs;
362 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800363
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 int _currentAllocs;
365 int _nAllocs;
366 int _maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800367};
368
Lee Thomason2c85a712012-01-31 08:24:24 -0800369
Lee Thomason56bdd022012-02-09 18:16:58 -0800370
371/**
372 Implements the interface to the "Visitor pattern" (see the Accept() method.)
373 If you call the Accept() method, it requires being passed a XMLVisitor
374 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200375 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800376 are simply called with Visit().
377
378 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200379 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800380
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700381 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 visiting). You need to only override methods that are interesting to you.
383
Thomas Roß08bdf502012-05-12 14:21:23 +0200384 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800385
386 You should never change the document from a callback.
387
388 @sa XMLNode::Accept()
389*/
390class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800391{
392public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800394
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 /// Visit a document.
396 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
397 return true;
398 }
399 /// Visit a document.
400 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
401 return true;
402 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800403
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700404 /// Visit an element.
405 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
406 return true;
407 }
408 /// Visit an element.
409 virtual bool VisitExit( const XMLElement& /*element*/ ) {
410 return true;
411 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800412
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700413 /// Visit a declaration.
414 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
415 return true;
416 }
417 /// Visit a text node.
418 virtual bool Visit( const XMLText& /*text*/ ) {
419 return true;
420 }
421 /// Visit a comment node.
422 virtual bool Visit( const XMLComment& /*comment*/ ) {
423 return true;
424 }
425 /// Visit an unknown node.
426 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
427 return true;
428 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800429};
430
431
U-Stream\Leeae25a442012-02-17 17:48:16 -0800432/*
433 Utility functionality.
434*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800435class XMLUtil
436{
Lee Thomasond1983222012-02-06 08:41:24 -0800437public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700438 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
439 // correct, but simple, and usually works.
440 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200441 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700442 ++p;
443 }
444 return p;
445 }
446 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200447 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700448 ++p;
449 }
450 return p;
451 }
452 static bool IsWhiteSpace( char p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200453 return !IsUTF8Continuation(p) && std::isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700454 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800455
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700456 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
457 int n = 0;
458 if ( p == q ) {
459 return true;
460 }
461 while( *p && *q && *p == *q && n<nChar ) {
462 ++p;
463 ++q;
464 ++n;
465 }
466 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
467 return true;
468 }
469 return false;
470 }
471 inline static int IsUTF8Continuation( const char p ) {
472 return p & 0x80;
473 }
474 inline static int IsAlphaNum( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200475 return ( anyByte < 128 ) ? std::isalnum( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700476 }
477 inline static int IsAlpha( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200478 return ( anyByte < 128 ) ? std::isalpha( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700479 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800480
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700481 static const char* ReadBOM( const char* p, bool* hasBOM );
482 // p is the starting location,
483 // the UTF-8 value of the entity will be placed in value, and length filled in.
484 static const char* GetCharacterRef( const char* p, char* value, int* length );
485 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700486
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700487 // converts primitive types to strings
488 static void ToStr( int v, char* buffer, int bufferSize );
489 static void ToStr( unsigned v, char* buffer, int bufferSize );
490 static void ToStr( bool v, char* buffer, int bufferSize );
491 static void ToStr( float v, char* buffer, int bufferSize );
492 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700493
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700494 // converts strings to primitive types
495 static bool ToInt( const char* str, int* value );
496 static bool ToUnsigned( const char* str, unsigned* value );
497 static bool ToBool( const char* str, bool* value );
498 static bool ToFloat( const char* str, float* value );
499 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800500};
501
Lee Thomason5cae8972012-01-24 18:03:07 -0800502
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800503/** XMLNode is a base class for every object that is in the
504 XML Document Object Model (DOM), except XMLAttributes.
505 Nodes have siblings, a parent, and children which can
506 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700507 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800508 be cast to its more defined type.
509
Thomas Roß08bdf502012-05-12 14:21:23 +0200510 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800511 When the XMLDocument gets deleted, all its Nodes
512 will also be deleted.
513
514 @verbatim
515 A Document can contain: Element (container or leaf)
516 Comment (leaf)
517 Unknown (leaf)
518 Declaration( leaf )
519
520 An Element can contain: Element (container or leaf)
521 Text (leaf)
522 Attributes (not on tree)
523 Comment (leaf)
524 Unknown (leaf)
525
526 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800527*/
Lee Thomasond1983222012-02-06 08:41:24 -0800528class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800529{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700530 friend class XMLDocument;
531 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800532public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800533
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 /// Get the XMLDocument that owns this XMLNode.
535 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700536 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 }
538 /// Get the XMLDocument that owns this XMLNode.
539 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700540 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800542
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700543 virtual XMLElement* ToElement() {
544 return 0; ///< Safely cast to an Element, or null.
545 }
546 virtual XMLText* ToText() {
547 return 0; ///< Safely cast to Text, or null.
548 }
549 virtual XMLComment* ToComment() {
550 return 0; ///< Safely cast to a Comment, or null.
551 }
552 virtual XMLDocument* ToDocument() {
553 return 0; ///< Safely cast to a Document, or null.
554 }
555 virtual XMLDeclaration* ToDeclaration() {
556 return 0; ///< Safely cast to a Declaration, or null.
557 }
558 virtual XMLUnknown* ToUnknown() {
559 return 0; ///< Safely cast to an Unknown, or null.
560 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800561
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700562 virtual const XMLElement* ToElement() const {
563 return 0;
564 }
565 virtual const XMLText* ToText() const {
566 return 0;
567 }
568 virtual const XMLComment* ToComment() const {
569 return 0;
570 }
571 virtual const XMLDocument* ToDocument() const {
572 return 0;
573 }
574 virtual const XMLDeclaration* ToDeclaration() const {
575 return 0;
576 }
577 virtual const XMLUnknown* ToUnknown() const {
578 return 0;
579 }
Lee Thomason751da522012-02-10 08:50:51 -0800580
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700581 /** The meaning of 'value' changes for the specific type.
582 @verbatim
583 Document: empty
584 Element: name of the element
585 Comment: the comment text
586 Unknown: the tag contents
587 Text: the text string
588 @endverbatim
589 */
590 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700591 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700593
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 /** Set the Value of an XML node.
595 @sa Value()
596 */
597 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800598
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700599 /// Get the parent of this node on the DOM.
600 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700601 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700603
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700605 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 }
Lee Thomason751da522012-02-10 08:50:51 -0800607
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 /// Returns true if this node has no children.
609 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700610 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 }
Lee Thomason751da522012-02-10 08:50:51 -0800612
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700613 /// Get the first child node, or null if none exists.
614 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700615 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700617
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700619 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700620 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700621
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700622 /** Get the first child element, or optionally the first child
623 element with the specified name.
624 */
625 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700626
627 XMLElement* FirstChildElement( const char* value=0 ) {
628 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800630
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700631 /// Get the last child node, or null if none exists.
632 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700633 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700635
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700636 XMLNode* LastChild() {
637 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
638 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800639
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700640 /** Get the last child element or optionally the last child
641 element with the specified name.
642 */
643 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700644
645 XMLElement* LastChildElement( const char* value=0 ) {
646 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700648
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 /// Get the previous (left) sibling node of this node.
650 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700651 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700652 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700653
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700655 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800657
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
659 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700660
661 XMLElement* PreviousSiblingElement( const char* value=0 ) {
662 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700664
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 /// Get the next (right) sibling node of this node.
666 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700667 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700668 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700669
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700671 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700673
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
675 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700676
677 XMLElement* NextSiblingElement( const char* value=0 ) {
678 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700679 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800680
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 /**
682 Add a child node as the last (right) child.
683 */
684 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800685
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 XMLNode* LinkEndChild( XMLNode* addThis ) {
687 return InsertEndChild( addThis );
688 }
689 /**
690 Add a child node as the first (left) child.
691 */
692 XMLNode* InsertFirstChild( XMLNode* addThis );
693 /**
694 Add a node after the specified child node.
695 */
696 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700697
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700698 /**
699 Delete all the children of this node.
700 */
701 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800702
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 /**
704 Delete a child of this node.
705 */
706 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800707
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 /**
709 Make a copy of this node, but not its children.
710 You may pass in a Document pointer that will be
711 the owner of the new Node. If the 'document' is
712 null, then the node returned will be allocated
713 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 Note: if called on a XMLDocument, this will return null.
716 */
717 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800718
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 /**
720 Test if 2 nodes are the same, but don't test children.
721 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800722
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 Note: if called on a XMLDocument, this will return false.
724 */
725 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800726
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
728 XML tree will be conditionally visited and the host will be called back
729 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800730
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
732 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
733 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800734
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 - http://www.saxproject.org/
738 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800739
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700740 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800741
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 An example of using Accept():
743 @verbatim
744 TiXmlPrinter printer;
745 tinyxmlDoc.Accept( &printer );
746 const char* xmlcstr = printer.CStr();
747 @endverbatim
748 */
749 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800750
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 // internal
752 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800753
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800754protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 XMLNode( XMLDocument* );
756 virtual ~XMLNode();
757 XMLNode( const XMLNode& ); // not supported
758 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700759
Lee Thomason624d43f2012-10-12 10:58:48 -0700760 XMLDocument* _document;
761 XMLNode* _parent;
762 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800763
Lee Thomason624d43f2012-10-12 10:58:48 -0700764 XMLNode* _firstChild;
765 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800766
Lee Thomason624d43f2012-10-12 10:58:48 -0700767 XMLNode* _prev;
768 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800769
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800770private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700771 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800773};
774
775
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800776/** XML text.
777
778 Note that a text node can have child element nodes, for example:
779 @verbatim
780 <root>This is <b>bold</b></root>
781 @endverbatim
782
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700783 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800784 and CDATA. It will default to the mode it was parsed from the XML file and
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700785 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800786 SetCDATA() and query it with CDATA().
787*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800788class XMLText : public XMLNode
789{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 friend class XMLBase;
791 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800792public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800794
Lee Thomason624d43f2012-10-12 10:58:48 -0700795 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 return this;
797 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700798 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700799 return this;
800 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800801
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700802 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700803 void SetCData( bool isCData ) {
804 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700805 }
806 /// Returns true if this is a CDATA text element.
807 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700808 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800810
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 char* ParseDeep( char*, StrPair* endTag );
812 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
813 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800814
Lee Thomason5492a1c2012-01-23 15:32:10 -0800815protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700816 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 virtual ~XMLText() {}
818 XMLText( const XMLText& ); // not supported
819 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800820
821private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700822 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800823};
824
825
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800826/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800827class XMLComment : public XMLNode
828{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700829 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800830public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 virtual XMLComment* ToComment() {
832 return this;
833 }
834 virtual const XMLComment* ToComment() const {
835 return this;
836 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800837
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700838 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800839
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700840 char* ParseDeep( char*, StrPair* endTag );
841 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
842 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800843
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800844protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700845 XMLComment( XMLDocument* doc );
846 virtual ~XMLComment();
847 XMLComment( const XMLComment& ); // not supported
848 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800849
Lee Thomason3f57d272012-01-11 15:30:03 -0800850private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800851};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800852
853
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800854/** In correct XML the declaration is the first entry in the file.
855 @verbatim
856 <?xml version="1.0" standalone="yes"?>
857 @endverbatim
858
859 TinyXML2 will happily read or write files without a declaration,
860 however.
861
862 The text of the declaration isn't interpreted. It is parsed
863 and written as a string.
864*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800865class XMLDeclaration : public XMLNode
866{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700867 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800868public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700869 virtual XMLDeclaration* ToDeclaration() {
870 return this;
871 }
872 virtual const XMLDeclaration* ToDeclaration() const {
873 return this;
874 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800875
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800877
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700878 char* ParseDeep( char*, StrPair* endTag );
879 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
880 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800881
882protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 XMLDeclaration( XMLDocument* doc );
884 virtual ~XMLDeclaration();
885 XMLDeclaration( const XMLDeclaration& ); // not supported
886 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800887};
888
889
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800890/** Any tag that tinyXml doesn't recognize is saved as an
891 unknown. It is a tag of text, but should not be modified.
892 It will be written back to the XML, unchanged, when the file
893 is saved.
894
895 DTD tags get thrown into TiXmlUnknowns.
896*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800897class XMLUnknown : public XMLNode
898{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700899 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800900public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700901 virtual XMLUnknown* ToUnknown() {
902 return this;
903 }
904 virtual const XMLUnknown* ToUnknown() const {
905 return this;
906 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800907
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700908 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800909
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700910 char* ParseDeep( char*, StrPair* endTag );
911 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
912 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800913
914protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 XMLUnknown( XMLDocument* doc );
916 virtual ~XMLUnknown();
917 XMLUnknown( const XMLUnknown& ); // not supported
918 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800919};
920
921
Lee Thomason1ff38e02012-02-14 18:18:16 -0800922enum {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700923 XML_NO_ERROR = 0,
924 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800925
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700926 XML_NO_ATTRIBUTE,
927 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800928
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700929 XML_ERROR_FILE_NOT_FOUND,
930 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
931 XML_ERROR_FILE_READ_ERROR,
932 XML_ERROR_ELEMENT_MISMATCH,
933 XML_ERROR_PARSING_ELEMENT,
934 XML_ERROR_PARSING_ATTRIBUTE,
935 XML_ERROR_IDENTIFYING_TAG,
936 XML_ERROR_PARSING_TEXT,
937 XML_ERROR_PARSING_CDATA,
938 XML_ERROR_PARSING_COMMENT,
939 XML_ERROR_PARSING_DECLARATION,
940 XML_ERROR_PARSING_UNKNOWN,
941 XML_ERROR_EMPTY_DOCUMENT,
942 XML_ERROR_MISMATCHED_ELEMENT,
943 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700944
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700945 XML_CAN_NOT_CONVERT_TEXT,
946 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800947};
948
949
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800950/** An attribute is a name-value pair. Elements have an arbitrary
951 number of attributes, each with a unique name.
952
953 @note The attributes are not XMLNodes. You may only query the
954 Next() attribute in a list.
955*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800956class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800957{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700958 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800959public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700960 const char* Name() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700961 return _name.GetStr(); ///< The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700962 }
963 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700964 return _value.GetStr(); ///< The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700965 }
966 const XMLAttribute* Next() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700967 return _next; ///< The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700968 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800969
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700970 /** IntAttribute interprets the attribute as an integer, and returns the value.
971 If the value isn't an integer, 0 will be returned. There is no error checking;
972 use QueryIntAttribute() if you need error checking.
973 */
974 int IntValue() const {
975 int i=0;
976 QueryIntValue( &i );
977 return i;
978 }
979 /// Query as an unsigned integer. See IntAttribute()
980 unsigned UnsignedValue() const {
981 unsigned i=0;
982 QueryUnsignedValue( &i );
983 return i;
984 }
985 /// Query as a boolean. See IntAttribute()
986 bool BoolValue() const {
987 bool b=false;
988 QueryBoolValue( &b );
989 return b;
990 }
991 /// Query as a double. See IntAttribute()
992 double DoubleValue() const {
993 double d=0;
994 QueryDoubleValue( &d );
995 return d;
996 }
997 /// Query as a float. See IntAttribute()
998 float FloatValue() const {
999 float f=0;
1000 QueryFloatValue( &f );
1001 return f;
1002 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001003
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001004 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
1005 in the provided paremeter. The function will return XML_NO_ERROR on success,
1006 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1007 */
1008 int QueryIntValue( int* value ) const;
1009 /// See QueryIntAttribute
1010 int QueryUnsignedValue( unsigned int* value ) const;
1011 /// See QueryIntAttribute
1012 int QueryBoolValue( bool* value ) const;
1013 /// See QueryIntAttribute
1014 int QueryDoubleValue( double* value ) const;
1015 /// See QueryIntAttribute
1016 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001017
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 /// Set the attribute to a string value.
1019 void SetAttribute( const char* value );
1020 /// Set the attribute to value.
1021 void SetAttribute( int value );
1022 /// Set the attribute to value.
1023 void SetAttribute( unsigned value );
1024 /// Set the attribute to value.
1025 void SetAttribute( bool value );
1026 /// Set the attribute to value.
1027 void SetAttribute( double value );
1028 /// Set the attribute to value.
1029 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001030
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001031private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001032 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001033
Lee Thomason624d43f2012-10-12 10:58:48 -07001034 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001035 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001036
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001037 XMLAttribute( const XMLAttribute& ); // not supported
1038 void operator=( const XMLAttribute& ); // not supported
1039 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001040
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001041 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001042
Lee Thomason624d43f2012-10-12 10:58:48 -07001043 mutable StrPair _name;
1044 mutable StrPair _value;
1045 XMLAttribute* _next;
1046 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001047};
1048
1049
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001050/** The element is a container class. It has a value, the element name,
1051 and can contain other elements, text, comments, and unknowns.
1052 Elements also contain an arbitrary number of attributes.
1053*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001054class XMLElement : public XMLNode
1055{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001056 friend class XMLBase;
1057 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001058public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001059 /// Get the name of an element (which is the Value() of the node.)
1060 const char* Name() const {
1061 return Value();
1062 }
1063 /// Set the name of the element.
1064 void SetName( const char* str, bool staticMem=false ) {
1065 SetValue( str, staticMem );
1066 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001067
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001068 virtual XMLElement* ToElement() {
1069 return this;
1070 }
1071 virtual const XMLElement* ToElement() const {
1072 return this;
1073 }
1074 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001075
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001076 /** Given an attribute name, Attribute() returns the value
1077 for the attribute of that name, or null if none
1078 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001079
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001080 @verbatim
1081 const char* value = ele->Attribute( "foo" );
1082 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001083
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001084 The 'value' parameter is normally null. However, if specified,
1085 the attribute will only be returned if the 'name' and 'value'
1086 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001087
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 @verbatim
1089 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1090 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001091
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001092 rather than:
1093 @verbatim
1094 if ( ele->Attribute( "foo" ) ) {
1095 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1096 }
1097 @endverbatim
1098 */
1099 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001100
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001101 /** Given an attribute name, IntAttribute() returns the value
1102 of the attribute interpreted as an integer. 0 will be
1103 returned if there is an error. For a method with error
1104 checking, see QueryIntAttribute()
1105 */
1106 int IntAttribute( const char* name ) const {
1107 int i=0;
1108 QueryIntAttribute( name, &i );
1109 return i;
1110 }
1111 /// See IntAttribute()
1112 unsigned UnsignedAttribute( const char* name ) const {
1113 unsigned i=0;
1114 QueryUnsignedAttribute( name, &i );
1115 return i;
1116 }
1117 /// See IntAttribute()
1118 bool BoolAttribute( const char* name ) const {
1119 bool b=false;
1120 QueryBoolAttribute( name, &b );
1121 return b;
1122 }
1123 /// See IntAttribute()
1124 double DoubleAttribute( const char* name ) const {
1125 double d=0;
1126 QueryDoubleAttribute( name, &d );
1127 return d;
1128 }
1129 /// See IntAttribute()
1130 float FloatAttribute( const char* name ) const {
1131 float f=0;
1132 QueryFloatAttribute( name, &f );
1133 return f;
1134 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001135
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001136 /** Given an attribute name, QueryIntAttribute() returns
1137 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1138 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1139 doesn't exist. If successful, the result of the conversion
1140 will be written to 'value'. If not successful, nothing will
1141 be written to 'value'. This allows you to provide default
1142 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001143
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001144 @verbatim
1145 int value = 10;
1146 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1147 @endverbatim
1148 */
Lee Thomason624d43f2012-10-12 10:58:48 -07001149 int QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001150 const XMLAttribute* a = FindAttribute( name );
1151 if ( !a ) {
1152 return XML_NO_ATTRIBUTE;
1153 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001154 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001155 }
1156 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001157 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001158 const XMLAttribute* a = FindAttribute( name );
1159 if ( !a ) {
1160 return XML_NO_ATTRIBUTE;
1161 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001162 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001163 }
1164 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001165 int QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 const XMLAttribute* a = FindAttribute( name );
1167 if ( !a ) {
1168 return XML_NO_ATTRIBUTE;
1169 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001170 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001171 }
1172 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001173 int QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001174 const XMLAttribute* a = FindAttribute( name );
1175 if ( !a ) {
1176 return XML_NO_ATTRIBUTE;
1177 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001178 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001179 }
1180 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001181 int QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001182 const XMLAttribute* a = FindAttribute( name );
1183 if ( !a ) {
1184 return XML_NO_ATTRIBUTE;
1185 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001186 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001187 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001188
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001189 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001190 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001191 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001192 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001193 }
1194 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001195 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001196 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001197 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001198 }
1199 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001200 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001201 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001202 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001203 }
1204 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001205 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001206 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001207 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 }
1209 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001210 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001211 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001212 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001213 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001214
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001215 /**
1216 Delete an attribute.
1217 */
1218 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001219
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 /// Return the first attribute in the list.
1221 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001222 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 }
1224 /// Query a specific attribute in the list.
1225 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001226
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001227 /** Convenience function for easy access to the text inside an element. Although easy
1228 and concise, GetText() is limited compared to getting the TiXmlText child
1229 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001230
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001231 If the first child of 'this' is a TiXmlText, the GetText()
1232 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001233
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001234 This is a convenient method for getting the text of simple contained text:
1235 @verbatim
1236 <foo>This is text</foo>
1237 const char* str = fooElement->GetText();
1238 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001239
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001240 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001241
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001242 Note that this function can be misleading. If the element foo was created from
1243 this XML:
1244 @verbatim
1245 <foo><b>This is text</b></foo>
1246 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001247
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001248 then the value of str would be null. The first child node isn't a text node, it is
1249 another element. From this XML:
1250 @verbatim
1251 <foo>This is <b>text</b></foo>
1252 @endverbatim
1253 GetText() will return "This is ".
1254 */
1255 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001256
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 /**
1258 Convenience method to query the value of a child text node. This is probably best
1259 shown by example. Given you have a document is this form:
1260 @verbatim
1261 <point>
1262 <x>1</x>
1263 <y>1.4</y>
1264 </point>
1265 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001266
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001267 The QueryIntText() and similar functions provide a safe and easier way to get to the
1268 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001269
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001270 @verbatim
1271 int x = 0;
1272 float y = 0; // types of x and y are contrived for example
1273 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1274 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1275 xElement->QueryIntText( &x );
1276 yElement->QueryFloatText( &y );
1277 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001278
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001279 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1280 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001281
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001282 */
1283 int QueryIntText( int* _value ) const;
1284 /// See QueryIntText()
1285 int QueryUnsignedText( unsigned* _value ) const;
1286 /// See QueryIntText()
1287 int QueryBoolText( bool* _value ) const;
1288 /// See QueryIntText()
1289 int QueryDoubleText( double* _value ) const;
1290 /// See QueryIntText()
1291 int QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001292
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001293 // internal:
1294 enum {
1295 OPEN, // <foo>
1296 CLOSED, // <foo/>
1297 CLOSING // </foo>
1298 };
1299 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 }
1302 char* ParseDeep( char* p, StrPair* endTag );
1303 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1304 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001305
Lee Thomason50adb4c2012-02-13 15:07:09 -08001306private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 XMLElement( XMLDocument* doc );
1308 virtual ~XMLElement();
1309 XMLElement( const XMLElement& ); // not supported
1310 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001311
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 XMLAttribute* FindAttribute( const char* name );
1313 XMLAttribute* FindOrCreateAttribute( const char* name );
1314 //void LinkAttribute( XMLAttribute* attrib );
1315 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001316
Lee Thomason624d43f2012-10-12 10:58:48 -07001317 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 // The attribute list is ordered; there is no 'lastAttribute'
1319 // because the list needs to be scanned for dupes before adding
1320 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001321 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001322};
1323
1324
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001325enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 PRESERVE_WHITESPACE,
1327 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001328};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001329
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001330
1331/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001332 It can be saved, loaded, and printed to the screen.
1333 All Nodes are connected and allocated to a Document.
1334 If the Document is deleted, all its Nodes are also deleted.
1335*/
Lee Thomason67d61312012-01-24 16:01:51 -08001336class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001337{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001338 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001339public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001340 /// constructor
1341 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1342 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001343
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001344 virtual XMLDocument* ToDocument() {
1345 return this;
1346 }
1347 virtual const XMLDocument* ToDocument() const {
1348 return this;
1349 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001350
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001351 /**
1352 Parse an XML file from a character string.
1353 Returns XML_NO_ERROR (0) on success, or
1354 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001355
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001356 You may optionally pass in the 'nBytes', which is
1357 the number of bytes which will be parsed. If not
1358 specified, TinyXML will assume 'xml' points to a
1359 null terminated string.
1360 */
1361 int Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 /**
1364 Load an XML file from disk.
1365 Returns XML_NO_ERROR (0) on success, or
1366 an errorID.
1367 */
1368 int LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001369
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001370 /**
1371 Load an XML file from disk. You are responsible
1372 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001373
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001374 Returns XML_NO_ERROR (0) on success, or
1375 an errorID.
1376 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001377 int LoadFile( std::FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001378
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 /**
1380 Save the XML file to disk.
1381 Returns XML_NO_ERROR (0) on success, or
1382 an errorID.
1383 */
1384 int SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001385
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 /**
1387 Save the XML file to disk. You are responsible
1388 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001389
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001390 Returns XML_NO_ERROR (0) on success, or
1391 an errorID.
1392 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001393 int SaveFile( std::FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001394
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001395 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001396 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001397 }
1398 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001399 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001400 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001401
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001402 /**
1403 Returns true if this document has a leading Byte Order Mark of UTF8.
1404 */
1405 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001406 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 }
1408 /** Sets whether to write the BOM when writing the file.
1409 */
1410 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001411 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001412 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001413
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001414 /** Return the root element of DOM. Equivalent to FirstChildElement().
1415 To get the first node, use FirstChild().
1416 */
1417 XMLElement* RootElement() {
1418 return FirstChildElement();
1419 }
1420 const XMLElement* RootElement() const {
1421 return FirstChildElement();
1422 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001423
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 /** Print the Document. If the Printer is not provided, it will
1425 print to stdout. If you provide Printer, this can print to a file:
1426 @verbatim
1427 XMLPrinter printer( fp );
1428 doc.Print( &printer );
1429 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001430
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 Or you can use a printer to print to memory:
1432 @verbatim
1433 XMLPrinter printer;
1434 doc->Print( &printer );
1435 // printer.CStr() has a const char* to the XML
1436 @endverbatim
1437 */
1438 void Print( XMLPrinter* streamer=0 );
1439 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001440
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 /**
1442 Create a new Element associated with
1443 this Document. The memory for the Element
1444 is managed by the Document.
1445 */
1446 XMLElement* NewElement( const char* name );
1447 /**
1448 Create a new Comment associated with
1449 this Document. The memory for the Comment
1450 is managed by the Document.
1451 */
1452 XMLComment* NewComment( const char* comment );
1453 /**
1454 Create a new Text associated with
1455 this Document. The memory for the Text
1456 is managed by the Document.
1457 */
1458 XMLText* NewText( const char* text );
1459 /**
1460 Create a new Declaration associated with
1461 this Document. The memory for the object
1462 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001463
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001464 If the 'text' param is null, the standard
1465 declaration is used.:
1466 @verbatim
1467 <?xml version="1.0" encoding="UTF-8"?>
1468 @endverbatim
1469 */
1470 XMLDeclaration* NewDeclaration( const char* text=0 );
1471 /**
1472 Create a new Unknown associated with
Lee Thomason624d43f2012-10-12 10:58:48 -07001473 this Document. The memory forthe object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001474 is managed by the Document.
1475 */
1476 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001477
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001478 /**
1479 Delete a node associated with this document.
1480 It will be unlinked from the DOM.
1481 */
1482 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001483 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001484 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001485
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001486 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001487
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 /// Return true if there was an error parsing the document.
1489 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001490 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001491 }
1492 /// Return the errorID.
1493 int ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001494 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001495 }
1496 /// Return a possibly helpful diagnostic location or string.
1497 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001498 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 }
1500 /// Return a possibly helpful secondary diagnostic location or string.
1501 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001502 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 }
1504 /// If there is an error, print it to stdout.
1505 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 // internal
1508 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001509
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001510 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1511 return 0;
1512 }
1513 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1514 return false;
1515 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001516
Lee Thomason3f57d272012-01-11 15:30:03 -08001517private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001518 XMLDocument( const XMLDocument& ); // not supported
1519 void operator=( const XMLDocument& ); // not supported
1520 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001521
Lee Thomason624d43f2012-10-12 10:58:48 -07001522 bool _writeBOM;
1523 bool _processEntities;
1524 int _errorID;
1525 Whitespace _whitespace;
1526 const char* _errorStr1;
1527 const char* _errorStr2;
1528 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001529
Lee Thomason624d43f2012-10-12 10:58:48 -07001530 MemPoolT< sizeof(XMLElement) > _elementPool;
1531 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1532 MemPoolT< sizeof(XMLText) > _textPool;
1533 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001534};
1535
Lee Thomason7c913cd2012-01-26 18:32:34 -08001536
Lee Thomason3ffdd392012-03-28 17:27:55 -07001537/**
1538 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001539 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001540 DOM structure. It is a separate utility class.
1541
1542 Take an example:
1543 @verbatim
1544 <Document>
1545 <Element attributeA = "valueA">
1546 <Child attributeB = "value1" />
1547 <Child attributeB = "value2" />
1548 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001549 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001550 @endverbatim
1551
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001552 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001553 easy to write a *lot* of code that looks like:
1554
1555 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001556 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001557 if ( root )
1558 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001559 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001560 if ( element )
1561 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001562 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001563 if ( child )
1564 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001565 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001566 if ( child2 )
1567 {
1568 // Finally do something useful.
1569 @endverbatim
1570
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001571 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001572 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001573 and correct to use:
1574
1575 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001576 XMLHandle docHandle( &document );
1577 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001578 if ( child2 )
1579 {
1580 // do something useful
1581 @endverbatim
1582
1583 Which is MUCH more concise and useful.
1584
1585 It is also safe to copy handles - internally they are nothing more than node pointers.
1586 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001587 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001588 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001589
1590 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001591*/
1592class XMLHandle
1593{
1594public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001595 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Lee Thomason624d43f2012-10-12 10:58:48 -07001596 XMLHandle( XMLNode* node ) {
1597 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001598 }
1599 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001600 XMLHandle( XMLNode& node ) {
1601 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 }
1603 /// Copy constructor
1604 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001605 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 }
1607 /// Assignment
1608 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001609 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001610 return *this;
1611 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001612
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001613 /// Get the first child of this handle.
1614 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001615 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 }
1617 /// Get the first child element of this handle.
1618 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001619 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001620 }
1621 /// Get the last child of this handle.
1622 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001623 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001624 }
1625 /// Get the last child element of this handle.
1626 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001627 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 }
1629 /// Get the previous sibling of this handle.
1630 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001631 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001632 }
1633 /// Get the previous sibling element of this handle.
1634 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001635 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001636 }
1637 /// Get the next sibling of this handle.
1638 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001639 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 }
1641 /// Get the next sibling element of this handle.
1642 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001643 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001644 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001645
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 /// Safe cast to XMLNode. This can return null.
1647 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001648 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001649 }
1650 /// Safe cast to XMLElement. This can return null.
1651 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001652 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001653 }
1654 /// Safe cast to XMLText. This can return null.
1655 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001656 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 }
1658 /// Safe cast to XMLUnknown. This can return null.
1659 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001660 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001661 }
1662 /// Safe cast to XMLDeclaration. This can return null.
1663 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001664 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001665 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001666
1667private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001668 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001669};
1670
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001671
1672/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001673 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1674 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001675*/
1676class XMLConstHandle
1677{
1678public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001679 XMLConstHandle( const XMLNode* node ) {
1680 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001682 XMLConstHandle( const XMLNode& node ) {
1683 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001684 }
1685 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001686 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001687 }
Lee Thomason8b899812012-04-04 15:58:16 -07001688
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001689 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001690 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 return *this;
1692 }
Lee Thomason8b899812012-04-04 15:58:16 -07001693
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001694 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001695 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001696 }
1697 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001698 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001699 }
1700 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001701 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001702 }
1703 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001704 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 }
1706 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001707 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 }
1709 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001710 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001711 }
1712 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001713 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 }
1715 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001716 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001717 }
Lee Thomason8b899812012-04-04 15:58:16 -07001718
1719
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001720 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001721 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001722 }
1723 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001724 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001725 }
1726 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001727 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 }
1729 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001733 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001734 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001735
Lee Thomason5cae8972012-01-24 18:03:07 -08001736private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001737 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001738};
Lee Thomason6f381b72012-03-02 12:59:39 -08001739
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001740
1741/**
1742 Printing functionality. The XMLPrinter gives you more
1743 options than the XMLDocument::Print() method.
1744
1745 It can:
1746 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001747 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001748 -# Print XML without a XMLDocument.
1749
1750 Print to Memory
1751
1752 @verbatim
1753 XMLPrinter printer;
1754 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001755 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001756 @endverbatim
1757
1758 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001759
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001760 You provide the file pointer.
1761 @verbatim
1762 XMLPrinter printer( fp );
1763 doc.Print( &printer );
1764 @endverbatim
1765
1766 Print without a XMLDocument
1767
1768 When loading, an XML parser is very useful. However, sometimes
1769 when saving, it just gets in the way. The code is often set up
1770 for streaming, and constructing the DOM is just overhead.
1771
1772 The Printer supports the streaming case. The following code
1773 prints out a trivially simple XML file without ever creating
1774 an XML document.
1775
1776 @verbatim
1777 XMLPrinter printer( fp );
1778 printer.OpenElement( "foo" );
1779 printer.PushAttribute( "foo", "bar" );
1780 printer.CloseElement();
1781 @endverbatim
1782*/
1783class XMLPrinter : public XMLVisitor
1784{
1785public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 /** Construct the printer. If the FILE* is specified,
1787 this will print to the FILE. Else it will print
1788 to memory, and the result is available in CStr().
1789 If 'compact' is set to true, then output is created
1790 with only required whitespace and newlines.
1791 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001792 XMLPrinter( std::FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001793 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001794
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 /** If streaming, write the BOM and declaration. */
1796 void PushHeader( bool writeBOM, bool writeDeclaration );
1797 /** If streaming, start writing an element.
1798 The element must be closed with CloseElement()
1799 */
1800 void OpenElement( const char* name );
1801 /// If streaming, add an attribute to an open element.
1802 void PushAttribute( const char* name, const char* value );
1803 void PushAttribute( const char* name, int value );
1804 void PushAttribute( const char* name, unsigned value );
1805 void PushAttribute( const char* name, bool value );
1806 void PushAttribute( const char* name, double value );
1807 /// If streaming, close the Element.
1808 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001809
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001810 /// Add a text node.
1811 void PushText( const char* text, bool cdata=false );
1812 /// Add a text node from an integer.
1813 void PushText( int value );
1814 /// Add a text node from an unsigned.
1815 void PushText( unsigned value );
1816 /// Add a text node from a bool.
1817 void PushText( bool value );
1818 /// Add a text node from a float.
1819 void PushText( float value );
1820 /// Add a text node from a double.
1821 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001822
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001823 /// Add a comment
1824 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001825
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001826 void PushDeclaration( const char* value );
1827 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001828
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001829 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1830 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1831 return true;
1832 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001833
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001834 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1835 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001836
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001837 virtual bool Visit( const XMLText& text );
1838 virtual bool Visit( const XMLComment& comment );
1839 virtual bool Visit( const XMLDeclaration& declaration );
1840 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001841
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001842 /**
1843 If in print to memory mode, return a pointer to
1844 the XML file in memory.
1845 */
1846 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001847 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001848 }
1849 /**
1850 If in print to memory mode, return the size
1851 of the XML file in memory. (Note the size returned
1852 includes the terminating null.)
1853 */
1854 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001855 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001856 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001857
1858private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001859 void SealElement();
1860 void PrintSpace( int depth );
1861 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1862 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001863
Lee Thomason624d43f2012-10-12 10:58:48 -07001864 bool _elementJustOpened;
1865 bool _firstElement;
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001866 std::FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001867 int _depth;
1868 int _textDepth;
1869 bool _processEntities;
1870 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001871
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 enum {
1873 ENTITY_RANGE = 64,
1874 BUF_SIZE = 200
1875 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001876 bool _entityFlag[ENTITY_RANGE];
1877 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001878
Lee Thomason624d43f2012-10-12 10:58:48 -07001879 DynArray< const char*, 10 > _stack;
1880 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001881#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001882 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001883#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001884};
1885
1886
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001887} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001888
1889
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001890#endif // TINYXML2_INCLUDED