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