1
/*
2
www.sourceforge.net/projects/tinyxml
3
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any
7
damages arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any
10
purpose, including commercial applications, and to alter it and
11
redistribute it freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must
14
not claim that you wrote the original software. If you use this
15
software in a product, an acknowledgment in the product documentation
16
would be appreciated but is not required.
17
18
2. Altered source versions must be plainly marked as such, and
19
must not be misrepresented as being the original software.
20
21
3. This notice may not be removed or altered from any source
22
distribution.
23
*/
24
25
26
#ifndef TINYXML_INCLUDED
27
#define TINYXML_INCLUDED
28
29
#ifdef _MSC_VER
30
#pragma warning( push )
31
#pragma warning( disable : 4530 )
32
#pragma warning( disable : 4786 )
33
#endif
34
35
#include <ctype.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <assert.h>
40
41
// Help out windows:
42
#if defined( _DEBUG ) && !defined( DEBUG )
43
#define DEBUG
44
#endif
45
46
#if defined( DEBUG ) && defined( _MSC_VER )
47
#include <windows.h>
48
#define TIXML_LOG OutputDebugString
49
#else
50
#define TIXML_LOG printf
51
#endif
52
53
#ifdef TIXML_USE_STL
54
	#include <string>
55
 	#include <iostream>
56
	#define TIXML_STRING	std::string
57
	#define TIXML_ISTREAM	std::istream
58
	#define TIXML_OSTREAM	std::ostream
59
#else
60
	#include "tinystr.h"
61
	#define TIXML_STRING	TiXmlString
62
	#define TIXML_OSTREAM	TiXmlOutStream
63
#endif
64
65
// Deprecated library function hell. Compilers want to use the
66
// new safe versions. This probably doesn't fully address the problem,
67
// but it gets closer. There are too many compilers for me to fully
68
// test. If you get compilation troubles, undefine TIXML_SAFE
69
70
#define TIXML_SAFE		// TinyXml isn't fully buffer overrun protected, safe code. This is work in progress.
71
#ifdef TIXML_SAFE
72
	#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
73
		// Microsoft visual studio, version 6 and higher.
74
		//#pragma message( "Using _sn* functions." )
75
		#define TIXML_SNPRINTF _snprintf
76
		#define TIXML_SNSCANF  _snscanf
77
	#elif defined(__GNUC__) && (__GNUC__ >= 3 )
78
		// GCC version 3 and higher.s
79
		//#warning( "Using sn* functions." )
80
		#define TIXML_SNPRINTF snprintf
81
		#define TIXML_SNSCANF  snscanf
82
	#endif
83
#endif	
84
85
class TiXmlDocument;
86
class TiXmlElement;
87
class TiXmlComment;
88
class TiXmlUnknown;
89
class TiXmlAttribute;
90
class TiXmlText;
91
class TiXmlDeclaration;
92
class TiXmlParsingData;
93
94
const int TIXML_MAJOR_VERSION = 2;
95
const int TIXML_MINOR_VERSION = 4;
96
const int TIXML_PATCH_VERSION = 0;
97
98
/*	Internal structure for tracking location of items 
99
	in the XML file.
100
*/
101
struct TiXmlCursor
102
{
103
	TiXmlCursor()		{ Clear(); }
104
	void Clear()		{ row = col = -1; }
105
106
	int row;	// 0 based.
107
	int col;	// 0 based.
108
};
109
110
111
// Only used by Attribute::Query functions
112
enum 
113
{ 
114
	TIXML_SUCCESS,
115
	TIXML_NO_ATTRIBUTE,
116
	TIXML_WRONG_TYPE
117
};
118
119
120
// Used by the parsing routines.
121
enum TiXmlEncoding
122
{
123
	TIXML_ENCODING_UNKNOWN,
124
	TIXML_ENCODING_UTF8,
125
	TIXML_ENCODING_LEGACY
126
};
127
128
const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
129
130
/** TiXmlBase is a base class for every class in TinyXml.
131
	It does little except to establish that TinyXml classes
132
	can be printed and provide some utility functions.
133
134
	In XML, the document and elements can contain
135
	other elements and other types of nodes.
136
137
	@verbatim
138
	A Document can contain:	Element	(container or leaf)
139
							Comment (leaf)
140
							Unknown (leaf)
141
							Declaration( leaf )
142
143
	An Element can contain:	Element (container or leaf)
144
							Text	(leaf)
145
							Attributes (not on tree)
146
							Comment (leaf)
147
							Unknown (leaf)
148
149
	A Decleration contains: Attributes (not on tree)
150
	@endverbatim
151
*/
152
class TiXmlBase
153
{
154
	friend class TiXmlNode;
155
	friend class TiXmlElement;
156
	friend class TiXmlDocument;
157
158
public:
159
	TiXmlBase()	:	userData(0) {}
160
	virtual ~TiXmlBase()					{}
161
162
	/**	All TinyXml classes can print themselves to a filestream.
163
		This is a formatted print, and will insert tabs and newlines.
164
		
165
		(For an unformatted stream, use the << operator.)
166
	*/
167
	virtual void Print( FILE* cfile, int depth ) const = 0;
168
169
	/**	The world does not agree on whether white space should be kept or
170
		not. In order to make everyone happy, these global, static functions
171
		are provided to set whether or not TinyXml will condense all white space
172
		into a single space or not. The default is to condense. Note changing this
173
		values is not thread safe.
174
	*/
175
	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
176
177
	/// Return the current white space setting.
178
	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
179
180
	/** Return the position, in the original source file, of this node or attribute.
181
		The row and column are 1-based. (That is the first row and first column is
182
		1,1). If the returns values are 0 or less, then the parser does not have
183
		a row and column value.
184
185
		Generally, the row and column value will be set when the TiXmlDocument::Load(),
186
		TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
187
		when the DOM was created from operator>>.
188
189
		The values reflect the initial load. Once the DOM is modified programmatically
190
		(by adding or changing nodes and attributes) the new values will NOT update to
191
		reflect changes in the document.
192
193
		There is a minor performance cost to computing the row and column. Computation
194
		can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
195
196
		@sa TiXmlDocument::SetTabSize()
197
	*/
198
	int Row() const			{ return location.row + 1; }
199
	int Column() const		{ return location.col + 1; }	///< See Row()
200
201
	void  SetUserData( void* user )			{ userData = user; }
202
	void* GetUserData()						{ return userData; }
203
204
	// Table that returs, for a given lead byte, the total number of bytes
205
	// in the UTF-8 sequence.
206
	static const int utf8ByteTable[256];
207
208
	virtual const char* Parse(	const char* p, 
209
								TiXmlParsingData* data, 
210
								TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
211
212
	enum
213
	{
214
		TIXML_NO_ERROR = 0,
215
		TIXML_ERROR,
216
		TIXML_ERROR_OPENING_FILE,
217
		TIXML_ERROR_OUT_OF_MEMORY,
218
		TIXML_ERROR_PARSING_ELEMENT,
219
		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
220
		TIXML_ERROR_READING_ELEMENT_VALUE,
221
		TIXML_ERROR_READING_ATTRIBUTES,
222
		TIXML_ERROR_PARSING_EMPTY,
223
		TIXML_ERROR_READING_END_TAG,
224
		TIXML_ERROR_PARSING_UNKNOWN,
225
		TIXML_ERROR_PARSING_COMMENT,
226
		TIXML_ERROR_PARSING_DECLARATION,
227
		TIXML_ERROR_DOCUMENT_EMPTY,
228
		TIXML_ERROR_EMBEDDED_NULL,
229
		TIXML_ERROR_PARSING_CDATA,
230
231
		TIXML_ERROR_STRING_COUNT
232
	};
233
234
protected:
235
236
	// See STL_STRING_BUG
237
	// Utility class to overcome a bug.
238
	class StringToBuffer
239
	{
240
	  public:
241
		StringToBuffer( const TIXML_STRING& str );
242
		~StringToBuffer();
243
		char* buffer;
244
	};
245
246
	static const char*	SkipWhiteSpace( const char*, TiXmlEncoding encoding );
247
	inline static bool	IsWhiteSpace( char c )		
248
	{ 
249
		return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); 
250
	}
251
252
	virtual void StreamOut (TIXML_OSTREAM *) const = 0;
253
254
	#ifdef TIXML_USE_STL
255
	    static bool	StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
256
	    static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
257
	#endif
258
259
	/*	Reads an XML name into the string provided. Returns
260
		a pointer just past the last character of the name,
261
		or 0 if the function has an error.
262
	*/
263
	static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
264
265
	/*	Reads text. Returns a pointer past the given end tag.
266
		Wickedly complex options, but it keeps the (sensitive) code in one place.
267
	*/
268
	static const char* ReadText(	const char* in,				// where to start
269
									TIXML_STRING* text,			// the string read
270
									bool ignoreWhiteSpace,		// whether to keep the white space
271
									const char* endTag,			// what ends this text
272
									bool ignoreCase,			// whether to ignore case in the end tag
273
									TiXmlEncoding encoding );	// the current encoding
274
275
	// If an entity has been found, transform it into a character.
276
	static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
277
278
	// Get a character, while interpreting entities.
279
	// The length can be from 0 to 4 bytes.
280
	inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
281
	{
282
		assert( p );
283
		if ( encoding == TIXML_ENCODING_UTF8 )
284
		{
285
			*length = utf8ByteTable[ *((unsigned char*)p) ];
286
			assert( *length >= 0 && *length < 5 );
287
		}
288
		else
289
		{
290
			*length = 1;
291
		}
292
293
		if ( *length == 1 )
294
		{
295
			if ( *p == '&' )
296
				return GetEntity( p, _value, length, encoding );
297
			*_value = *p;
298
			return p+1;
299
		}
300
		else if ( *length )
301
		{
302
			//strncpy( _value, p, *length );	// lots of compilers don't like this function (unsafe),
303
												// and the null terminator isn't needed
304
			for( int i=0; p[i] && i<*length; ++i ) {
305
				_value[i] = p[i];
306
			}
307
			return p + (*length);
308
		}
309
		else
310
		{
311
			// Not valid text.
312
			return 0;
313
		}
314
	}
315
316
	// Puts a string to a stream, expanding entities as it goes.
317
	// Note this should not contian the '<', '>', etc, or they will be transformed into entities!
318
	static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
319
320
	static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
321
322
	// Return true if the next characters in the stream are any of the endTag sequences.
323
	// Ignore case only works for english, and should only be relied on when comparing
324
	// to English words: StringEqual( p, "version", true ) is fine.
325
	static bool StringEqual(	const char* p,
326
								const char* endTag,
327
								bool ignoreCase,
328
								TiXmlEncoding encoding );
329
330
	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
331
332
	TiXmlCursor location;
333
334
    /// Field containing a generic user pointer
335
	void*			userData;
336
	
337
	// None of these methods are reliable for any language except English.
338
	// Good for approximation, not great for accuracy.
339
	static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
340
	static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
341
	inline static int ToLower( int v, TiXmlEncoding encoding )
342
	{
343
		if ( encoding == TIXML_ENCODING_UTF8 )
344
		{
345
			if ( v < 128 ) return tolower( v );
346
			return v;
347
		}
348
		else
349
		{
350
			return tolower( v );
351
		}
352
	}
353
	static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
354
355
private:
356
	TiXmlBase( const TiXmlBase& );				// not implemented.
357
	void operator=( const TiXmlBase& base );	// not allowed.
358
359
	struct Entity
360
	{
361
		const char*     str;
362
		unsigned int	strLength;
363
		char		    chr;
364
	};
365
	enum
366
	{
367
		NUM_ENTITY = 5,
368
		MAX_ENTITY_LENGTH = 6
369
370
	};
371
	static Entity entity[ NUM_ENTITY ];
372
	static bool condenseWhiteSpace;
373
};
374
375
376
/** The parent class for everything in the Document Object Model.
377
	(Except for attributes).
378
	Nodes have siblings, a parent, and children. A node can be
379
	in a document, or stand on its own. The type of a TiXmlNode
380
	can be queried, and it can be cast to its more defined type.
381
*/
382
class TiXmlNode : public TiXmlBase
383
{
384
	friend class TiXmlDocument;
385
	friend class TiXmlElement;
386
387
public:
388
	#ifdef TIXML_USE_STL	
389
390
	    /** An input stream operator, for every class. Tolerant of newlines and
391
		    formatting, but doesn't expect them.
392
	    */
393
	    friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
394
395
	    /** An output stream operator, for every class. Note that this outputs
396
		    without any newlines or formatting, as opposed to Print(), which
397
		    includes tabs and new lines.
398
399
		    The operator<< and operator>> are not completely symmetric. Writing
400
		    a node to a stream is very well defined. You'll get a nice stream
401
		    of output, without any extra whitespace or newlines.
402
		    
403
		    But reading is not as well defined. (As it always is.) If you create
404
		    a TiXmlElement (for example) and read that from an input stream,
405
		    the text needs to define an element or junk will result. This is
406
		    true of all input streams, but it's worth keeping in mind.
407
408
		    A TiXmlDocument will read nodes until it reads a root element, and
409
			all the children of that root element.
410
	    */	
411
	    friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
412
413
		/// Appends the XML node or attribute to a std::string.
414
		friend std::string& operator<< (std::string& out, const TiXmlNode& base );
415
416
	#else
417
	    // Used internally, not part of the public API.
418
	    friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
419
	#endif
420
421
	/** The types of XML nodes supported by TinyXml. (All the
422
			unsupported types are picked up by UNKNOWN.)
423
	*/
424
	enum NodeType
425
	{
426
		DOCUMENT,
427
		ELEMENT,
428
		COMMENT,
429
		UNKNOWN,
430
		TEXT,
431
		DECLARATION,
432
		TYPECOUNT
433
	};
434
435
	virtual ~TiXmlNode();
436
437
	/** The meaning of 'value' changes for the specific type of
438
		TiXmlNode.
439
		@verbatim
440
		Document:	filename of the xml file
441
		Element:	name of the element
442
		Comment:	the comment text
443
		Unknown:	the tag contents
444
		Text:		the text string
445
		@endverbatim
446
447
		The subclasses will wrap this function.
448
	*/
449
	const char *Value() const { return value.c_str (); }
450
451
    #ifdef TIXML_USE_STL
452
	/** Return Value() as a std::string. If you only use STL,
453
	    this is more efficient than calling Value().
454
		Only available in STL mode.
455
	*/
456
	const std::string& ValueStr() const { return value; }
457
	#endif
458
459
	/** Changes the value of the node. Defined as:
460
		@verbatim
461
		Document:	filename of the xml file
462
		Element:	name of the element
463
		Comment:	the comment text
464
		Unknown:	the tag contents
465
		Text:		the text string
466
		@endverbatim
467
	*/
468
	void SetValue(const char * _value) { value = _value;}
469
470
    #ifdef TIXML_USE_STL
471
	/// STL std::string form.
472
	void SetValue( const std::string& _value )    
473
	{	  
474
		StringToBuffer buf( _value );
475
		SetValue( buf.buffer ? buf.buffer : "" );    	
476
	}	
477
	#endif
478
479
	/// Delete all the children of this node. Does not affect 'this'.
480
	void Clear();
481
482
	/// One step up the DOM.
483
	TiXmlNode* Parent()							{ return parent; }
484
	const TiXmlNode* Parent() const				{ return parent; }
485
486
	const TiXmlNode* FirstChild()	const	{ return firstChild; }		///< The first child of this node. Will be null if there are no children.
487
	TiXmlNode* FirstChild()					{ return firstChild; }
488
	const TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.
489
	TiXmlNode* FirstChild( const char * value );						///< The first child of this node with the matching 'value'. Will be null if none found.
490
491
	const TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
492
	TiXmlNode* LastChild()	{ return lastChild; }
493
	const TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.
494
	TiXmlNode* LastChild( const char * value );	
495
496
    #ifdef TIXML_USE_STL
497
	const TiXmlNode* FirstChild( const std::string& _value ) const	{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
498
	TiXmlNode* FirstChild( const std::string& _value )				{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
499
	const TiXmlNode* LastChild( const std::string& _value ) const	{	return LastChild (_value.c_str ());	}	///< STL std::string form.
500
	TiXmlNode* LastChild( const std::string& _value )				{	return LastChild (_value.c_str ());	}	///< STL std::string form.
501
	#endif
502
503
	/** An alternate way to walk the children of a node.
504
		One way to iterate over nodes is:
505
		@verbatim
506
			for( child = parent->FirstChild(); child; child = child->NextSibling() )
507
		@endverbatim
508
509
		IterateChildren does the same thing with the syntax:
510
		@verbatim
511
			child = 0;
512
			while( child = parent->IterateChildren( child ) )
513
		@endverbatim
514
515
		IterateChildren takes the previous child as input and finds
516
		the next one. If the previous child is null, it returns the
517
		first. IterateChildren will return null when done.
518
	*/
519
	const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
520
	TiXmlNode* IterateChildren( TiXmlNode* previous );
521
522
	/// This flavor of IterateChildren searches for children with a particular 'value'
523
	const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
524
	TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous );
525
526
    #ifdef TIXML_USE_STL
527
	const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const	{	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
528
	TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) {	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
529
	#endif
530
531
	/** Add a new node related to this. Adds a child past the LastChild.
532
		Returns a pointer to the new object or NULL if an error occured.
533
	*/
534
	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
535
536
537
	/** Add a new node related to this. Adds a child past the LastChild.
538
539
		NOTE: the node to be added is passed by pointer, and will be
540
		henceforth owned (and deleted) by tinyXml. This method is efficient
541
		and avoids an extra copy, but should be used with care as it
542
		uses a different memory model than the other insert functions.
543
544
		@sa InsertEndChild
545
	*/
546
	TiXmlNode* LinkEndChild( TiXmlNode* addThis );
547
548
	/** Add a new node related to this. Adds a child before the specified child.
549
		Returns a pointer to the new object or NULL if an error occured.
550
	*/
551
	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
552
553
	/** Add a new node related to this. Adds a child after the specified child.
554
		Returns a pointer to the new object or NULL if an error occured.
555
	*/
556
	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
557
558
	/** Replace a child of this node.
559
		Returns a pointer to the new object or NULL if an error occured.
560
	*/
561
	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
562
563
	/// Delete a child of this node.
564
	bool RemoveChild( TiXmlNode* removeThis );
565
566
	/// Navigate to a sibling node.
567
	const TiXmlNode* PreviousSibling() const			{ return prev; }
568
	TiXmlNode* PreviousSibling()						{ return prev; }
569
570
	/// Navigate to a sibling node.
571
	const TiXmlNode* PreviousSibling( const char * ) const;
572
	TiXmlNode* PreviousSibling( const char * );
573
574
    #ifdef TIXML_USE_STL
575
	const TiXmlNode* PreviousSibling( const std::string& _value ) const	{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
576
	TiXmlNode* PreviousSibling( const std::string& _value ) 			{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
577
	const TiXmlNode* NextSibling( const std::string& _value) const		{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
578
	TiXmlNode* NextSibling( const std::string& _value) 					{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
579
	#endif
580
581
	/// Navigate to a sibling node.
582
	const TiXmlNode* NextSibling() const				{ return next; }
583
	TiXmlNode* NextSibling()							{ return next; }
584
585
	/// Navigate to a sibling node with the given 'value'.
586
	const TiXmlNode* NextSibling( const char * ) const;
587
	TiXmlNode* NextSibling( const char * );
588
589
	/** Convenience function to get through elements.
590
		Calls NextSibling and ToElement. Will skip all non-Element
591
		nodes. Returns 0 if there is not another element.
592
	*/
593
	const TiXmlElement* NextSiblingElement() const;
594
	TiXmlElement* NextSiblingElement();
595
596
	/** Convenience function to get through elements.
597
		Calls NextSibling and ToElement. Will skip all non-Element
598
		nodes. Returns 0 if there is not another element.
599
	*/
600
	const TiXmlElement* NextSiblingElement( const char * ) const;
601
	TiXmlElement* NextSiblingElement( const char * );
602
603
    #ifdef TIXML_USE_STL
604
	const TiXmlElement* NextSiblingElement( const std::string& _value) const	{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
605
	TiXmlElement* NextSiblingElement( const std::string& _value)				{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
606
	#endif
607
608
	/// Convenience function to get through elements.
609
	const TiXmlElement* FirstChildElement()	const;
610
	TiXmlElement* FirstChildElement();
611
612
	/// Convenience function to get through elements.
613
	const TiXmlElement* FirstChildElement( const char * value ) const;
614
	TiXmlElement* FirstChildElement( const char * value );
615
616
    #ifdef TIXML_USE_STL
617
	const TiXmlElement* FirstChildElement( const std::string& _value ) const	{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
618
	TiXmlElement* FirstChildElement( const std::string& _value )				{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
619
	#endif
620
621
	/** Query the type (as an enumerated value, above) of this node.
622
		The possible types are: DOCUMENT, ELEMENT, COMMENT,
623
								UNKNOWN, TEXT, and DECLARATION.
624
	*/
625
	virtual int Type() const	{ return type; }
626
627
	/** Return a pointer to the Document this node lives in.
628
		Returns null if not in a document.
629
	*/
630
	const TiXmlDocument* GetDocument() const;
631
	TiXmlDocument* GetDocument();
632
633
	/// Returns true if this node has no children.
634
	bool NoChildren() const						{ return !firstChild; }
635
636
	const TiXmlDocument* ToDocument()	const		{ return ( this && type == DOCUMENT ) ? (const TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
637
	const TiXmlElement*  ToElement() const			{ return ( this && type == ELEMENT  ) ? (const TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
638
	const TiXmlComment*  ToComment() const			{ return ( this && type == COMMENT  ) ? (const TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
639
	const TiXmlUnknown*  ToUnknown() const			{ return ( this && type == UNKNOWN  ) ? (const TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
640
	const TiXmlText*	   ToText()    const		{ return ( this && type == TEXT     ) ? (const TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
641
	const TiXmlDeclaration* ToDeclaration() const	{ return ( this && type == DECLARATION ) ? (const TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
642
643
	TiXmlDocument* ToDocument()			{ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
644
	TiXmlElement*  ToElement()			{ return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
645
	TiXmlComment*  ToComment()			{ return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
646
	TiXmlUnknown*  ToUnknown()			{ return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
647
	TiXmlText*	   ToText()   			{ return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
648
	TiXmlDeclaration* ToDeclaration()	{ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
649
650
	/** Create an exact duplicate of this node and return it. The memory must be deleted
651
		by the caller. 
652
	*/
653
	virtual TiXmlNode* Clone() const = 0;
654
655
protected:
656
	TiXmlNode( NodeType _type );
657
658
	// Copy to the allocated object. Shared functionality between Clone, Copy constructor,
659
	// and the assignment operator.
660
	void CopyTo( TiXmlNode* target ) const;
661
662
	#ifdef TIXML_USE_STL
663
	    // The real work of the input operator.
664
	    virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
665
	#endif
666
667
	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
668
	TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
669
670
	TiXmlNode*		parent;
671
	NodeType		type;
672
673
	TiXmlNode*		firstChild;
674
	TiXmlNode*		lastChild;
675
676
	TIXML_STRING	value;
677
678
	TiXmlNode*		prev;
679
	TiXmlNode*		next;
680
681
private:
682
	TiXmlNode( const TiXmlNode& );				// not implemented.
683
	void operator=( const TiXmlNode& base );	// not allowed.
684
};
685
686
687
/** An attribute is a name-value pair. Elements have an arbitrary
688
	number of attributes, each with a unique name.
689
690
	@note The attributes are not TiXmlNodes, since they are not
691
		  part of the tinyXML document object model. There are other
692
		  suggested ways to look at this problem.
693
*/
694
class TiXmlAttribute : public TiXmlBase
695
{
696
	friend class TiXmlAttributeSet;
697
698
public:
699
	/// Construct an empty attribute.
700
	TiXmlAttribute() : TiXmlBase()
701
	{
702
		document = 0;
703
		prev = next = 0;
704
	}
705
706
	#ifdef TIXML_USE_STL
707
	/// std::string constructor.
708
	TiXmlAttribute( const std::string& _name, const std::string& _value )
709
	{
710
		name = _name;
711
		value = _value;
712
		document = 0;
713
		prev = next = 0;
714
	}
715
	#endif
716
717
	/// Construct an attribute with a name and value.
718
	TiXmlAttribute( const char * _name, const char * _value )
719
	{
720
		name = _name;
721
		value = _value;
722
		document = 0;
723
		prev = next = 0;
724
	}
725
726
	const char*		Name()  const		{ return name.c_str (); }		///< Return the name of this attribute.
727
	const char*		Value() const		{ return value.c_str (); }		///< Return the value of this attribute.
728
	int				IntValue() const;									///< Return the value of this attribute, converted to an integer.
729
	double			DoubleValue() const;								///< Return the value of this attribute, converted to a double.
730
731
	/** QueryIntValue examines the value string. It is an alternative to the
732
		IntValue() method with richer error checking.
733
		If the value is an integer, it is stored in 'value' and 
734
		the call returns TIXML_SUCCESS. If it is not
735
		an integer, it returns TIXML_WRONG_TYPE.
736
737
		A specialized but useful call. Note that for success it returns 0,
738
		which is the opposite of almost all other TinyXml calls.
739
	*/
740
	int QueryIntValue( int* _value ) const;
741
	/// QueryDoubleValue examines the value string. See QueryIntValue().
742
	int QueryDoubleValue( double* _value ) const;
743
744
	void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
745
	void SetValue( const char* _value )	{ value = _value; }				///< Set the value.
746
747
	void SetIntValue( int _value );										///< Set the value from an integer.
748
	void SetDoubleValue( double _value );								///< Set the value from a double.
749
750
    #ifdef TIXML_USE_STL
751
	/// STL std::string form.
752
	void SetName( const std::string& _name )	
753
	{	
754
		StringToBuffer buf( _name );
755
		SetName ( buf.buffer ? buf.buffer : "error" );	
756
	}
757
	/// STL std::string form.	
758
	void SetValue( const std::string& _value )	
759
	{	
760
		StringToBuffer buf( _value );
761
		SetValue( buf.buffer ? buf.buffer : "error" );	
762
	}
763
	#endif
764
765
	/// Get the next sibling attribute in the DOM. Returns null at end.
766
	const TiXmlAttribute* Next() const;
767
	TiXmlAttribute* Next();
768
	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
769
	const TiXmlAttribute* Previous() const;
770
	TiXmlAttribute* Previous();
771
772
	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
773
	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
774
	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
775
776
	/*	Attribute parsing starts: first letter of the name
777
						 returns: the next char after the value end quote
778
	*/
779
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
780
781
	// Prints this Attribute to a FILE stream.
782
	virtual void Print( FILE* cfile, int depth ) const;
783
784
	virtual void StreamOut( TIXML_OSTREAM * out ) const;
785
	// [internal use]
786
	// Set the document pointer so the attribute can report errors.
787
	void SetDocument( TiXmlDocument* doc )	{ document = doc; }
788
789
private:
790
	TiXmlAttribute( const TiXmlAttribute& );				// not implemented.
791
	void operator=( const TiXmlAttribute& base );	// not allowed.
792
793
	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
794
	TIXML_STRING name;
795
	TIXML_STRING value;
796
	TiXmlAttribute*	prev;
797
	TiXmlAttribute*	next;
798
};
799
800
801
/*	A class used to manage a group of attributes.
802
	It is only used internally, both by the ELEMENT and the DECLARATION.
803
	
804
	The set can be changed transparent to the Element and Declaration
805
	classes that use it, but NOT transparent to the Attribute
806
	which has to implement a next() and previous() method. Which makes
807
	it a bit problematic and prevents the use of STL.
808
809
	This version is implemented with circular lists because:
810
		- I like circular lists
811
		- it demonstrates some independence from the (typical) doubly linked list.
812
*/
813
class TiXmlAttributeSet
814
{
815
public:
816
	TiXmlAttributeSet();
817
	~TiXmlAttributeSet();
818
819
	void Add( TiXmlAttribute* attribute );
820
	void Remove( TiXmlAttribute* attribute );
821
822
	const TiXmlAttribute* First()	const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
823
	TiXmlAttribute* First()					{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
824
	const TiXmlAttribute* Last() const		{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
825
	TiXmlAttribute* Last()					{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
826
827
	const TiXmlAttribute*	Find( const char * name ) const;
828
	TiXmlAttribute*	Find( const char * name );
829
830
private:
831
	//*ME:	Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
832
	//*ME:	this class must be also use a hidden/disabled copy-constructor !!!
833
	TiXmlAttributeSet( const TiXmlAttributeSet& );	// not allowed
834
	void operator=( const TiXmlAttributeSet& );	// not allowed (as TiXmlAttribute)
835
836
	TiXmlAttribute sentinel;
837
};
838
839
840
/** The element is a container class. It has a value, the element name,
841
	and can contain other elements, text, comments, and unknowns.
842
	Elements also contain an arbitrary number of attributes.
843
*/
844
class TiXmlElement : public TiXmlNode
845
{
846
public:
847
	/// Construct an element.
848
	TiXmlElement (const char * in_value);
849
850
	#ifdef TIXML_USE_STL
851
	/// std::string constructor.
852
	TiXmlElement( const std::string& _value );
853
	#endif
854
855
	TiXmlElement( const TiXmlElement& );
856
857
	void operator=( const TiXmlElement& base );
858
859
	virtual ~TiXmlElement();
860
861
	/** Given an attribute name, Attribute() returns the value
862
		for the attribute of that name, or null if none exists.
863
	*/
864
	const char* Attribute( const char* name ) const;
865
866
	/** Given an attribute name, Attribute() returns the value
867
		for the attribute of that name, or null if none exists.
868
		If the attribute exists and can be converted to an integer,
869
		the integer value will be put in the return 'i', if 'i'
870
		is non-null.
871
	*/
872
	const char* Attribute( const char* name, int* i ) const;
873
874
	/** Given an attribute name, Attribute() returns the value
875
		for the attribute of that name, or null if none exists.
876
		If the attribute exists and can be converted to an double,
877
		the double value will be put in the return 'd', if 'd'
878
		is non-null.
879
	*/
880
	const char* Attribute( const char* name, double* d ) const;
881
882
	/** QueryIntAttribute examines the attribute - it is an alternative to the
883
		Attribute() method with richer error checking.
884
		If the attribute is an integer, it is stored in 'value' and 
885
		the call returns TIXML_SUCCESS. If it is not
886
		an integer, it returns TIXML_WRONG_TYPE. If the attribute
887
		does not exist, then TIXML_NO_ATTRIBUTE is returned.
888
	*/	
889
	int QueryIntAttribute( const char* name, int* _value ) const;
890
	/// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
891
	int QueryDoubleAttribute( const char* name, double* _value ) const;
892
	/// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
893
	int QueryFloatAttribute( const char* name, float* _value ) const {
894
		double d;
895
		int result = QueryDoubleAttribute( name, &d );
896
		if ( result == TIXML_SUCCESS ) {
897
			*_value = (float)d;
898
		}
899
		return result;
900
	}
901
902
	/** Sets an attribute of name to a given value. The attribute
903
		will be created if it does not exist, or changed if it does.
904
	*/
905
	void SetAttribute( const char* name, const char * _value );
906
907
    #ifdef TIXML_USE_STL
908
	const char* Attribute( const std::string& name ) const				{ return Attribute( name.c_str() ); }
909
	const char* Attribute( const std::string& name, int* i ) const		{ return Attribute( name.c_str(), i ); }
910
	const char* Attribute( const std::string& name, double* d ) const	{ return Attribute( name.c_str(), d ); }
911
	int QueryIntAttribute( const std::string& name, int* _value ) const	{ return QueryIntAttribute( name.c_str(), _value ); }
912
	int QueryDoubleAttribute( const std::string& name, double* _value ) const { return QueryDoubleAttribute( name.c_str(), _value ); }
913
914
	/// STL std::string form.
915
	void SetAttribute( const std::string& name, const std::string& _value )	
916
	{	
917
		StringToBuffer n( name );
918
		StringToBuffer v( _value );
919
		if ( n.buffer && v.buffer )
920
			SetAttribute (n.buffer, v.buffer );	
921
	}	
922
	///< STL std::string form.
923
	void SetAttribute( const std::string& name, int _value )	
924
	{	
925
		StringToBuffer n( name );
926
		if ( n.buffer )
927
			SetAttribute (n.buffer, _value);	
928
	}	
929
	#endif
930
931
	/** Sets an attribute of name to a given value. The attribute
932
		will be created if it does not exist, or changed if it does.
933
	*/
934
	void SetAttribute( const char * name, int value );
935
936
	/** Sets an attribute of name to a given value. The attribute
937
		will be created if it does not exist, or changed if it does.
938
	*/
939
	void SetDoubleAttribute( const char * name, double value );
940
941
	/** Deletes an attribute with the given name.
942
	*/
943
	void RemoveAttribute( const char * name );
944
    #ifdef TIXML_USE_STL
945
	void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
946
	#endif
947
948
	const TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
949
	TiXmlAttribute* FirstAttribute() 				{ return attributeSet.First(); }
950
	const TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
951
	TiXmlAttribute* LastAttribute()					{ return attributeSet.Last(); }
952
953
	/** Convenience function for easy access to the text inside an element. Although easy
954
		and concise, GetText() is limited compared to getting the TiXmlText child
955
		and accessing it directly.
956
	
957
		If the first child of 'this' is a TiXmlText, the GetText()
958
		returs the character string of the Text node, else null is returned.
959
960
		This is a convenient method for getting the text of simple contained text:
961
		@verbatim
962
		<foo>This is text</foo>
963
		const char* str = fooElement->GetText();
964
		@endverbatim
965
966
		'str' will be a pointer to "This is text". 
967
		
968
		Note that this function can be misleading. If the element foo was created from
969
		this XML:
970
		@verbatim
971
		<foo><b>This is text</b></foo> 
972
		@endverbatim
973
974
		then the value of str would be null. The first child node isn't a text node, it is
975
		another element. From this XML:
976
		@verbatim
977
		<foo>This is <b>text</b></foo> 
978
		@endverbatim
979
		GetText() will return "This is ".
980
981
		WARNING: GetText() accesses a child node - don't become confused with the 
982
				 similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are 
983
				 safe type casts on the referenced node.
984
	*/
985
	const char* GetText() const;
986
987
	/// Creates a new Element and returns it - the returned element is a copy.
988
	virtual TiXmlNode* Clone() const;
989
	// Print the Element to a FILE stream.
990
	virtual void Print( FILE* cfile, int depth ) const;
991
992
	/*	Attribtue parsing starts: next char past '<'
993
						 returns: next char past '>'
994
	*/
995
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
996
997
protected:
998
999
	void CopyTo( TiXmlElement* target ) const;
1000
	void ClearThis();	// like clear, but initializes 'this' object as well
1001
1002
	// Used to be public [internal use]
1003
	#ifdef TIXML_USE_STL
1004
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1005
	#endif
1006
	virtual void StreamOut( TIXML_OSTREAM * out ) const;
1007
1008
	/*	[internal use]
1009
		Reads the "value" of the element -- another element, or text.
1010
		This should terminate with the current end tag.
1011
	*/
1012
	const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
1013
1014
private:
1015
1016
	TiXmlAttributeSet attributeSet;
1017
};
1018
1019
1020
/**	An XML comment.
1021
*/
1022
class TiXmlComment : public TiXmlNode
1023
{
1024
public:
1025
	/// Constructs an empty comment.
1026
	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
1027
	TiXmlComment( const TiXmlComment& );
1028
	void operator=( const TiXmlComment& base );
1029
1030
	virtual ~TiXmlComment()	{}
1031
1032
	/// Returns a copy of this Comment.
1033
	virtual TiXmlNode* Clone() const;
1034
	/// Write this Comment to a FILE stream.
1035
	virtual void Print( FILE* cfile, int depth ) const;
1036
1037
	/*	Attribtue parsing starts: at the ! of the !--
1038
						 returns: next char past '>'
1039
	*/
1040
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1041
1042
protected:
1043
	void CopyTo( TiXmlComment* target ) const;
1044
1045
	// used to be public
1046
	#ifdef TIXML_USE_STL
1047
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1048
	#endif
1049
	virtual void StreamOut( TIXML_OSTREAM * out ) const;
1050
1051
private:
1052
1053
};
1054
1055
1056
/** XML text. A text node can have 2 ways to output the next. "normal" output 
1057
	and CDATA. It will default to the mode it was parsed from the XML file and
1058
	you generally want to leave it alone, but you can change the output mode with 
1059
	SetCDATA() and query it with CDATA().
1060
*/
1061
class TiXmlText : public TiXmlNode
1062
{
1063
	friend class TiXmlElement;
1064
public:
1065
	/** Constructor for text element. By default, it is treated as 
1066
		normal, encoded text. If you want it be output as a CDATA text
1067
		element, set the parameter _cdata to 'true'
1068
	*/
1069
	TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
1070
	{
1071
		SetValue( initValue );
1072
		cdata = false;
1073
	}
1074
	virtual ~TiXmlText() {}
1075
1076
	#ifdef TIXML_USE_STL
1077
	/// Constructor.
1078
	TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
1079
	{
1080
		SetValue( initValue );
1081
		cdata = false;
1082
	}
1083
	#endif
1084
1085
	TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT )	{ copy.CopyTo( this ); }
1086
	void operator=( const TiXmlText& base )							 	{ base.CopyTo( this ); }
1087
1088
	/// Write this text object to a FILE stream.
1089
	virtual void Print( FILE* cfile, int depth ) const;
1090
1091
	/// Queries whether this represents text using a CDATA section.
1092
	bool CDATA()					{ return cdata; }
1093
	/// Turns on or off a CDATA representation of text.
1094
	void SetCDATA( bool _cdata )	{ cdata = _cdata; }
1095
1096
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1097
1098
protected :
1099
	///  [internal use] Creates a new Element and returns it.
1100
	virtual TiXmlNode* Clone() const;
1101
	void CopyTo( TiXmlText* target ) const;
1102
1103
	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1104
	bool Blank() const;	// returns true if all white space and new lines
1105
	// [internal use]
1106
	#ifdef TIXML_USE_STL
1107
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1108
	#endif
1109
1110
private:
1111
	bool cdata;			// true if this should be input and output as a CDATA style text element
1112
};
1113
1114
1115
/** In correct XML the declaration is the first entry in the file.
1116
	@verbatim
1117
		<?xml version="1.0" standalone="yes"?>
1118
	@endverbatim
1119
1120
	TinyXml will happily read or write files without a declaration,
1121
	however. There are 3 possible attributes to the declaration:
1122
	version, encoding, and standalone.
1123
1124
	Note: In this version of the code, the attributes are
1125
	handled as special cases, not generic attributes, simply
1126
	because there can only be at most 3 and they are always the same.
1127
*/
1128
class TiXmlDeclaration : public TiXmlNode
1129
{
1130
public:
1131
	/// Construct an empty declaration.
1132
	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
1133
1134
#ifdef TIXML_USE_STL
1135
	/// Constructor.
1136
	TiXmlDeclaration(	const std::string& _version,
1137
						const std::string& _encoding,
1138
						const std::string& _standalone );
1139
#endif
1140
1141
	/// Construct.
1142
	TiXmlDeclaration(	const char* _version,
1143
						const char* _encoding,
1144
						const char* _standalone );
1145
1146
	TiXmlDeclaration( const TiXmlDeclaration& copy );
1147
	void operator=( const TiXmlDeclaration& copy );
1148
1149
	virtual ~TiXmlDeclaration()	{}
1150
1151
	/// Version. Will return an empty string if none was found.
1152
	const char *Version() const			{ return version.c_str (); }
1153
	/// Encoding. Will return an empty string if none was found.
1154
	const char *Encoding() const		{ return encoding.c_str (); }
1155
	/// Is this a standalone document?
1156
	const char *Standalone() const		{ return standalone.c_str (); }
1157
1158
	/// Creates a copy of this Declaration and returns it.
1159
	virtual TiXmlNode* Clone() const;
1160
	/// Print this declaration to a FILE stream.
1161
	virtual void Print( FILE* cfile, int depth ) const;
1162
1163
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1164
1165
protected:
1166
	void CopyTo( TiXmlDeclaration* target ) const;
1167
	// used to be public
1168
	#ifdef TIXML_USE_STL
1169
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1170
	#endif
1171
	virtual void StreamOut ( TIXML_OSTREAM * out) const;
1172
1173
private:
1174
1175
	TIXML_STRING version;
1176
	TIXML_STRING encoding;
1177
	TIXML_STRING standalone;
1178
};
1179
1180
1181
/** Any tag that tinyXml doesn't recognize is saved as an
1182
	unknown. It is a tag of text, but should not be modified.
1183
	It will be written back to the XML, unchanged, when the file
1184
	is saved.
1185
1186
	DTD tags get thrown into TiXmlUnknowns.
1187
*/
1188
class TiXmlUnknown : public TiXmlNode
1189
{
1190
public:
1191
	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN )	{}
1192
	virtual ~TiXmlUnknown() {}
1193
1194
	TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN )		{ copy.CopyTo( this ); }
1195
	void operator=( const TiXmlUnknown& copy )										{ copy.CopyTo( this ); }
1196
1197
	/// Creates a copy of this Unknown and returns it.
1198
	virtual TiXmlNode* Clone() const;
1199
	/// Print this Unknown to a FILE stream.
1200
	virtual void Print( FILE* cfile, int depth ) const;
1201
1202
	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1203
1204
protected:
1205
	void CopyTo( TiXmlUnknown* target ) const;
1206
1207
	#ifdef TIXML_USE_STL
1208
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1209
	#endif
1210
	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1211
1212
private:
1213
1214
};
1215
1216
1217
/** Always the top level node. A document binds together all the
1218
	XML pieces. It can be saved, loaded, and printed to the screen.
1219
	The 'value' of a document node is the xml file name.
1220
*/
1221
class TiXmlDocument : public TiXmlNode
1222
{
1223
public:
1224
	/// Create an empty document, that has no name.
1225
	TiXmlDocument();
1226
	/// Create a document with a name. The name of the document is also the filename of the xml.
1227
	TiXmlDocument( const char * documentName );
1228
1229
	#ifdef TIXML_USE_STL
1230
	/// Constructor.
1231
	TiXmlDocument( const std::string& documentName );
1232
	#endif
1233
1234
	TiXmlDocument( const TiXmlDocument& copy );
1235
	void operator=( const TiXmlDocument& copy );
1236
1237
	virtual ~TiXmlDocument() {}
1238
1239
	/** Load a file using the current document value.
1240
		Returns true if successful. Will delete any existing
1241
		document data before loading.
1242
	*/
1243
	bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1244
	/// Save a file using the current document value. Returns true if successful.
1245
	bool SaveFile() const;
1246
	/// Load a file using the given filename. Returns true if successful.
1247
	bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1248
	/// Save a file using the given filename. Returns true if successful.
1249
	bool SaveFile( const char * filename ) const;
1250
1251
	#ifdef TIXML_USE_STL
1252
	bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING )			///< STL std::string version.
1253
	{
1254
		StringToBuffer f( filename );
1255
		return ( f.buffer && LoadFile( f.buffer, encoding ));
1256
	}
1257
	bool SaveFile( const std::string& filename ) const		///< STL std::string version.
1258
	{
1259
		StringToBuffer f( filename );
1260
		return ( f.buffer && SaveFile( f.buffer ));
1261
	}
1262
	#endif
1263
1264
	/** Parse the given null terminated block of xml data. Passing in an encoding to this
1265
		method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
1266
		to use that encoding, regardless of what TinyXml might otherwise try to detect.
1267
	*/
1268
	virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1269
1270
	/** Get the root element -- the only top level element -- of the document.
1271
		In well formed XML, there should only be one. TinyXml is tolerant of
1272
		multiple elements at the document level.
1273
	*/
1274
	const TiXmlElement* RootElement() const		{ return FirstChildElement(); }
1275
	TiXmlElement* RootElement()					{ return FirstChildElement(); }
1276
1277
	/** If an error occurs, Error will be set to true. Also,
1278
		- The ErrorId() will contain the integer identifier of the error (not generally useful)
1279
		- The ErrorDesc() method will return the name of the error. (very useful)
1280
		- The ErrorRow() and ErrorCol() will return the location of the error (if known)
1281
	*/	
1282
	bool Error() const						{ return error; }
1283
1284
	/// Contains a textual (english) description of the error if one occurs.
1285
	const char * ErrorDesc() const	{ return errorDesc.c_str (); }
1286
1287
	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
1288
		prefer the ErrorId, this function will fetch it.
1289
	*/
1290
	int ErrorId()	const				{ return errorId; }
1291
1292
	/** Returns the location (if known) of the error. The first column is column 1, 
1293
		and the first row is row 1. A value of 0 means the row and column wasn't applicable
1294
		(memory errors, for example, have no row/column) or the parser lost the error. (An
1295
		error in the error reporting, in that case.)
1296
1297
		@sa SetTabSize, Row, Column
1298
	*/
1299
	int ErrorRow()	{ return errorLocation.row+1; }
1300
	int ErrorCol()	{ return errorLocation.col+1; }	///< The column where the error occured. See ErrorRow()
1301
1302
	/** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
1303
		to report the correct values for row and column. It does not change the output
1304
		or input in any way.
1305
		
1306
		By calling this method, with a tab size
1307
		greater than 0, the row and column of each node and attribute is stored
1308
		when the file is loaded. Very useful for tracking the DOM back in to
1309
		the source file.
1310
1311
		The tab size is required for calculating the location of nodes. If not
1312
		set, the default of 4 is used. The tabsize is set per document. Setting
1313
		the tabsize to 0 disables row/column tracking.
1314
1315
		Note that row and column tracking is not supported when using operator>>.
1316
1317
		The tab size needs to be enabled before the parse or load. Correct usage:
1318
		@verbatim
1319
		TiXmlDocument doc;
1320
		doc.SetTabSize( 8 );
1321
		doc.Load( "myfile.xml" );
1322
		@endverbatim
1323
1324
		@sa Row, Column
1325
	*/
1326
	void SetTabSize( int _tabsize )		{ tabsize = _tabsize; }
1327
1328
	int TabSize() const	{ return tabsize; }
1329
1330
	/** If you have handled the error, it can be reset with this call. The error
1331
		state is automatically cleared if you Parse a new XML block.
1332
	*/
1333
	void ClearError()						{	error = false; 
1334
												errorId = 0; 
1335
												errorDesc = ""; 
1336
												errorLocation.row = errorLocation.col = 0; 
1337
												//errorLocation.last = 0; 
1338
											}
1339
1340
	/** Dump the document to standard out. */
1341
	void Print() const						{ Print( stdout, 0 ); }
1342
1343
	/// Print this Document to a FILE stream.
1344
	virtual void Print( FILE* cfile, int depth = 0 ) const;
1345
	// [internal use]
1346
	void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
1347
1348
protected :
1349
	virtual void StreamOut ( TIXML_OSTREAM * out) const;
1350
	// [internal use]
1351
	virtual TiXmlNode* Clone() const;
1352
	#ifdef TIXML_USE_STL
1353
	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1354
	#endif
1355
1356
private:
1357
	void CopyTo( TiXmlDocument* target ) const;
1358
1359
	bool error;
1360
	int  errorId;
1361
	TIXML_STRING errorDesc;
1362
	int tabsize;
1363
	TiXmlCursor errorLocation;
1364
	bool useMicrosoftBOM;		// the UTF-8 BOM were found when read. Note this, and try to write.
1365
};
1366
1367
1368
/**
1369
	A TiXmlHandle is a class that wraps a node pointer with null checks; this is
1370
	an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
1371
	DOM structure. It is a separate utility class.
1372
1373
	Take an example:
1374
	@verbatim
1375
	<Document>
1376
		<Element attributeA = "valueA">
1377
			<Child attributeB = "value1" />
1378
			<Child attributeB = "value2" />
1379
		</Element>
1380
	<Document>
1381
	@endverbatim
1382
1383
	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 
1384
	easy to write a *lot* of code that looks like:
1385
1386
	@verbatim
1387
	TiXmlElement* root = document.FirstChildElement( "Document" );
1388
	if ( root )
1389
	{
1390
		TiXmlElement* element = root->FirstChildElement( "Element" );
1391
		if ( element )
1392
		{
1393
			TiXmlElement* child = element->FirstChildElement( "Child" );
1394
			if ( child )
1395
			{
1396
				TiXmlElement* child2 = child->NextSiblingElement( "Child" );
1397
				if ( child2 )
1398
				{
1399
					// Finally do something useful.
1400
	@endverbatim
1401
1402
	And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
1403
	of such code. A TiXmlHandle checks for null	pointers so it is perfectly safe 
1404
	and correct to use:
1405
1406
	@verbatim
1407
	TiXmlHandle docHandle( &document );
1408
	TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
1409
	if ( child2 )
1410
	{
1411
		// do something useful
1412
	@endverbatim
1413
1414
	Which is MUCH more concise and useful.
1415
1416
	It is also safe to copy handles - internally they are nothing more than node pointers.
1417
	@verbatim
1418
	TiXmlHandle handleCopy = handle;
1419
	@endverbatim
1420
1421
	What they should not be used for is iteration:
1422
1423
	@verbatim
1424
	int i=0; 
1425
	while ( true )
1426
	{
1427
		TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
1428
		if ( !child )
1429
			break;
1430
		// do something
1431
		++i;
1432
	}
1433
	@endverbatim
1434
1435
	It seems reasonable, but it is in fact two embedded while loops. The Child method is 
1436
	a linear walk to find the element, so this code would iterate much more than it needs 
1437
	to. Instead, prefer:
1438
1439
	@verbatim
1440
	TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
1441
1442
	for( child; child; child=child->NextSiblingElement() )
1443
	{
1444
		// do something
1445
	}
1446
	@endverbatim
1447
*/
1448
class TiXmlHandle
1449
{
1450
public:
1451
	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1452
	TiXmlHandle( TiXmlNode* _node )					{ this->node = _node; }
1453
	/// Copy constructor
1454
	TiXmlHandle( const TiXmlHandle& ref )			{ this->node = ref.node; }
1455
	TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
1456
1457
	/// Return a handle to the first child node.
1458
	TiXmlHandle FirstChild() const;
1459
	/// Return a handle to the first child node with the given name.
1460
	TiXmlHandle FirstChild( const char * value ) const;
1461
	/// Return a handle to the first child element.
1462
	TiXmlHandle FirstChildElement() const;
1463
	/// Return a handle to the first child element with the given name.
1464
	TiXmlHandle FirstChildElement( const char * value ) const;
1465
1466
	/** Return a handle to the "index" child with the given name. 
1467
		The first child is 0, the second 1, etc.
1468
	*/
1469
	TiXmlHandle Child( const char* value, int index ) const;
1470
	/** Return a handle to the "index" child. 
1471
		The first child is 0, the second 1, etc.
1472
	*/
1473
	TiXmlHandle Child( int index ) const;
1474
	/** Return a handle to the "index" child element with the given name. 
1475
		The first child element is 0, the second 1, etc. Note that only TiXmlElements
1476
		are indexed: other types are not counted.
1477
	*/
1478
	TiXmlHandle ChildElement( const char* value, int index ) const;
1479
	/** Return a handle to the "index" child element. 
1480
		The first child element is 0, the second 1, etc. Note that only TiXmlElements
1481
		are indexed: other types are not counted.
1482
	*/
1483
	TiXmlHandle ChildElement( int index ) const;
1484
1485
	#ifdef TIXML_USE_STL
1486
	TiXmlHandle FirstChild( const std::string& _value ) const				{ return FirstChild( _value.c_str() ); }
1487
	TiXmlHandle FirstChildElement( const std::string& _value ) const		{ return FirstChildElement( _value.c_str() ); }
1488
1489
	TiXmlHandle Child( const std::string& _value, int index ) const			{ return Child( _value.c_str(), index ); }
1490
	TiXmlHandle ChildElement( const std::string& _value, int index ) const	{ return ChildElement( _value.c_str(), index ); }
1491
	#endif
1492
1493
	/// Return the handle as a TiXmlNode. This may return null.
1494
	TiXmlNode* Node() const			{ return node; } 
1495
	/// Return the handle as a TiXmlElement. This may return null.
1496
	TiXmlElement* Element() const	{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1497
	/// Return the handle as a TiXmlText. This may return null.
1498
	TiXmlText* Text() const			{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1499
	/// Return the handle as a TiXmlUnknown. This may return null;
1500
	TiXmlUnknown* Unknown() const			{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1501
1502
private:
1503
	TiXmlNode* node;
1504
};
1505
1506
#ifdef _MSC_VER
1507
#pragma warning( pop )
1508
#endif
1509
1510
#endif