1 /*
2 Copyright (c) 2000 Lee Thomason (www.grinninglizard.com)
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any
6 damages arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any
9 purpose, including commercial applications, and to alter it and
10 redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
16 
17 2. Altered source versions must be plainly marked as such, and
18 must not be misrepresented as being the original software.
19 
20 3. This notice may not be removed or altered from any source
21 distribution.
22 */
23 
24 
25 #ifndef TINYXML_INCLUDED
26 #define TINYXML_INCLUDED
27 
28 #pragma warning( disable : 4530 )
29 #pragma warning( disable : 4786 )
30 
31 #include <string>
32 #include <stdio.h>
33 #include <assert.h>
34 
35 class TiXmlDocument;
36 class TiXmlElement;
37 class TiXmlComment;
38 class TiXmlUnknown;
39 class TiXmlAttribute;
40 class TiXmlText;
41 class TiXmlDeclaration;
42 
43 
44 // Help out windows:
45 #if defined( _DEBUG ) && !defined( DEBUG )
46 	#define DEBUG
47 #endif
48 
49 #if defined( DEBUG ) && defined( _MSC_VER )
50 	#include <windows.h>
51 	#define TIXML_LOG OutputDebugString
52 #else
53 	#define TIXML_LOG printf
54 #endif
55 
56 
57 /** TiXmlBase is a base class for every class in TinyXml.
58 	It does little except to establish that TinyXml classes
59 	can be printed and provide some utility functions.
60 
61 	In XML, the document and elements can contain
62 	other elements and other types of nodes.
63 
64 	@verbatim
65 	A Document can contain:	Element	(container or leaf)
66 							Comment (leaf)
67 							Unknown (leaf)
68 							Declaration( leaf )
69 
70 	An Element can contain:	Element (container or leaf)
71 							Text	(leaf)
72 							Attributes (not on tree)
73 							Comment (leaf)
74 							Unknown (leaf)
75 
76 	A Decleration contains: Attributes (not on tree)
77 	@endverbatim
78 */
79 class TiXmlBase
80 {
81 	friend class TiXmlNode;
82 	friend class TiXmlElement;
83 	friend class TiXmlDocument;
84 
85   public:
TiXmlBase()86 	TiXmlBase()								{}
~TiXmlBase()87 	virtual ~TiXmlBase()					{}
88 
89 	/**	All TinyXml classes can print themselves to a filestream.
90 		This is a formatted print, and will insert tabs and newlines.
91 
92 		(For an unformatted stream, use the << operator.)
93 	*/
94  	virtual void Print( FILE* cfile, int depth ) const = 0;
95 
96 	// [internal] Underlying implementation of the operator <<
97 	virtual void StreamOut ( std::ostream* out ) const = 0;
98 
99 	/**	The world does not agree on whether white space should be kept or
100 		not. In order to make everyone happy, these global, static functions
101 		are provided to set whether or not TinyXml will condense all white space
102 		into a single space or not. The default is to condense. Note changing these
103 		values is not thread safe.
104 	*/
SetCondenseWhiteSpace(bool condense)105 	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
106 
107 	/// Return the current white space setting.
IsWhiteSpaceCondensed()108 	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
109 
110   protected:
111 	static const char* SkipWhiteSpace( const char* );
112 	static bool StreamWhiteSpace( std::istream* in, std::string* tag );
IsWhiteSpace(int c)113 	static bool IsWhiteSpace( int c )		{ return ( isspace( c ) || c == '\n' || c == '\r' ); }
114 
115 	/*	Read to the specified character.
116 		Returns true if the character found and no error.
117 	*/
118 	static bool StreamTo( std::istream* in, int character, std::string* tag );
119 
120 	/*	Reads an XML name into the string provided. Returns
121 		a pointer just past the last character of the name,
122 		or 0 if the function has an error.
123 	*/
124 	static const char* ReadName( const char*, std::string* name );
125 
126 	/*	Reads text. Returns a pointer past the given end tag.
127 		Wickedly complex options, but it keeps the (sensitive) code in one place.
128 	*/
129 	static const char* ReadText(	const char* in,				// where to start
130 									std::string* text,			// the string read
131 									bool ignoreWhiteSpace,		// whether to keep the white space
132 									const char* endTag,			// what ends this text
133 									bool ignoreCase );			// whether to ignore case in the end tag
134 
135 	virtual const char* Parse( const char* p ) = 0;
136 
137 	// If an entity has been found, transform it into a character.
138 	static const char* GetEntity( const char* in, char* value );
139 
140 	// Get a character, while interpreting entities.
GetChar(const char * p,char * value)141 	inline static const char* GetChar( const char* p, char* value )
142 											{
143 												assert( p );
144 												if ( *p == '&' )
145 												{
146 													return GetEntity( p, value );
147 												}
148 												else
149 												{
150 													*value = *p;
151 													return p+1;
152 												}
153 											}
154 
155 	// Puts a string to a stream, expanding entities as it goes.
156 	// Note this should not contian the '<', '>', etc, or they will be transformed into entities!
157 	static void PutString( const std::string& str, std::ostream* stream );
158 
159 	// Return true if the next characters in the stream are any of the endTag sequences.
160 	bool static StringEqual(	const char* p,
161 								const char* endTag,
162 								bool ignoreCase );
163 
164 
165 	enum
166 	{
167 		TIXML_NO_ERROR = 0,
168 		TIXML_ERROR,
169 		TIXML_ERROR_OPENING_FILE,
170 		TIXML_ERROR_OUT_OF_MEMORY,
171 		TIXML_ERROR_PARSING_ELEMENT,
172 		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
173 		TIXML_ERROR_READING_ELEMENT_VALUE,
174 		TIXML_ERROR_READING_ATTRIBUTES,
175 		TIXML_ERROR_PARSING_EMPTY,
176 		TIXML_ERROR_READING_END_TAG,
177 		TIXML_ERROR_PARSING_UNKNOWN,
178 		TIXML_ERROR_PARSING_COMMENT,
179 		TIXML_ERROR_PARSING_DECLARATION,
180 		TIXML_ERROR_DOCUMENT_EMPTY,
181 
182 		TIXML_ERROR_STRING_COUNT
183 	};
184 	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
185 
186   private:
187 	struct Entity
188 	{
189 		const char*     str;
190 		unsigned int	strLength;
191 		int			    chr;
192 	};
193 	enum
194 	{
195 		NUM_ENTITY = 5,
196 		MAX_ENTITY_LENGTH = 6
197 
198 	};
199 	static Entity entity[ NUM_ENTITY ];
200 	static bool condenseWhiteSpace;
201 };
202 
203 
204 /** The parent class for everything in the Document Object Model.
205 	(Except for attributes, which are contained in elements.)
206 	Nodes have siblings, a parent, and children. A node can be
207 	in a document, or stand on its own. The type of a TiXmlNode
208 	can be queried, and it can be cast to its more defined type.
209 */
210 class TiXmlNode : public TiXmlBase
211 {
212   public:
213 
214 	/** An output stream operator, for every class. Note that this outputs
215 		without any newlines or formatting, as opposed to Print(), which
216 		includes tabs and new lines.
217 
218 		The operator<< and operator>> are not completely symmetric. Writing
219 		a node to a stream is very well defined. You'll get a nice stream
220 		of output, without any extra whitespace or newlines.
221 
222 		But reading is not as well defined. (As it always is.) If you create
223 		a TiXmlElement (for example) and read that from an input stream,
224 		the text needs to define an element or junk will result. This is
225 		true of all input streams, but it's worth keeping in mind.
226 
227 		A TiXmlDocument will read nodes until it reads a root element.
228 	*/
229 	friend std::ostream& operator<< ( std::ostream& out, const TiXmlNode& base )
230 	{
231 		base.StreamOut( &out );
232 		return out;
233 	}
234 
235 	/** An input stream operator, for every class. Tolerant of newlines and
236 		formatting, but doesn't expect them.
237 	*/
238 	friend std::istream& operator>> ( std::istream& in, TiXmlNode& base )
239 	{
240 		std::string tag;
241 		tag.reserve( 8 * 1000 );
242 		base.StreamIn( &in, &tag );
243 
244 		base.Parse( tag.c_str() );
245 		return in;
246 	}
247 
248 	/** The types of XML nodes supported by TinyXml. (All the
249 		unsupported types are picked up by UNKNOWN.)
250 	*/
251 	enum NodeType
252 	{
253 		DOCUMENT,
254 		ELEMENT,
255 		COMMENT,
256 		UNKNOWN,
257 		TEXT,
258 		DECLARATION,
259 		TYPECOUNT
260 	};
261 
262 	virtual ~TiXmlNode();
263 
264 	/** The meaning of 'value' changes for the specific type of
265 		TiXmlNode.
266 		@verbatim
267 		Document:	filename of the xml file
268 		Element:	name of the element
269 		Comment:	the comment text
270 		Unknown:	the tag contents
271 		Text:		the text string
272 		@endverbatim
273 
274 		The subclasses will wrap this function.
275 	*/
Value()276 	const std::string& Value()	const			{ return value; }
277 
278 	/** Changes the value of the node. Defined as:
279 		@verbatim
280 		Document:	filename of the xml file
281 		Element:	name of the element
282 		Comment:	the comment text
283 		Unknown:	the tag contents
284 		Text:		the text string
285 		@endverbatim
286 	*/
SetValue(const std::string & _value)287 	void SetValue( const std::string& _value )		{ value = _value; }
288 
289 	/// Delete all the children of this node. Does not affect 'this'.
290 	void Clear();
291 
292 	/// One step up the DOM.
Parent()293 	TiXmlNode* Parent() const					{ return parent; }
294 
FirstChild()295 	TiXmlNode* FirstChild()	const	{ return firstChild; }		///< The first child of this node. Will be null if there are no children.
296 	TiXmlNode* FirstChild( const std::string& value ) const;	///< The first child of this node with the matching 'value'. Will be null if none found.
297 
LastChild()298 	TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
299 	TiXmlNode* LastChild( const std::string& value ) const;		/// The last child of this node matching 'value'. Will be null if there are no children.
300 
301 	/** An alternate way to walk the children of a node.
302 		One way to iterate over nodes is:
303 		@verbatim
304 			for( child = parent->FirstChild(); child; child = child->NextSibling() )
305 		@endverbatim
306 
307 		IterateChildren does the same thing with the syntax:
308 		@verbatim
309 			child = 0;
310 			while( child = parent->IterateChildren( child ) )
311 		@endverbatim
312 
313 		IterateChildren takes the previous child as input and finds
314 		the next one. If the previous child is null, it returns the
315 		first. IterateChildren will return null when done.
316 	*/
317 	TiXmlNode* IterateChildren( TiXmlNode* previous ) const;
318 
319 	/// This flavor of IterateChildren searches for children with a particular 'value'
320 	TiXmlNode* IterateChildren( const std::string& value, TiXmlNode* previous ) const;
321 
322 	/** Add a new node related to this. Adds a child past the LastChild.
323 		Returns a pointer to the new object or NULL if an error occured.
324 	*/
325 	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
326 
327 	/** Add a new node related to this. Adds a child before the specified child.
328 		Returns a pointer to the new object or NULL if an error occured.
329 	*/
330 	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
331 
332 	/** Add a new node related to this. Adds a child after the specified child.
333 		Returns a pointer to the new object or NULL if an error occured.
334 	*/
335 	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
336 
337 	/** Replace a child of this node.
338 		Returns a pointer to the new object or NULL if an error occured.
339 	*/
340 	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
341 
342 	/// Delete a child of this node.
343 	bool RemoveChild( TiXmlNode* removeThis );
344 
345 	/// Navigate to a sibling node.
PreviousSibling()346 	TiXmlNode* PreviousSibling() const			{ return prev; }
347 
348 	/// Navigate to a sibling node.
349 	TiXmlNode* PreviousSibling( const std::string& ) const;
350 
351 	/// Navigate to a sibling node.
NextSibling()352 	TiXmlNode* NextSibling() const				{ return next; }
353 
354 	/// Navigate to a sibling node with the given 'value'.
355 	TiXmlNode* NextSibling( const std::string& ) const;
356 
357 	/** Convenience function to get through elements.
358 		Calls NextSibling and ToElement. Will skip all non-Element
359 		nodes. Returns 0 if there is not another element.
360 	*/
361 	TiXmlElement* NextSiblingElement() const;
362 
363 	/** Convenience function to get through elements.
364 		Calls NextSibling and ToElement. Will skip all non-Element
365 		nodes. Returns 0 if there is not another element.
366 	*/
367 	TiXmlElement* NextSiblingElement( const std::string& ) const;
368 
369 	/// Convenience function to get through elements.
370 	TiXmlElement* FirstChildElement()	const;
371 
372 	/// Convenience function to get through elements.
373 	TiXmlElement* FirstChildElement( const std::string& value ) const;
374 
375 	/// Query the type (as an enumerated value, above) of this node.
Type()376 	virtual int Type() const	{ return type; }
377 
378 	/** Return a pointer to the Document this node lives in.
379 		Returns null if not in a document.
380 	*/
381 	TiXmlDocument* GetDocument() const;
382 
383 	/// Returns true if this node has no children.
NoChildren()384 	bool NoChildren() const						{ return !firstChild; }
385 
ToDocument()386 	TiXmlDocument* ToDocument()	const		{ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToElement()387 	TiXmlElement*  ToElement() const		{ return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToComment()388 	TiXmlComment*  ToComment() const		{ return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToUnknown()389 	TiXmlUnknown*  ToUnknown() const		{ return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToText()390 	TiXmlText*	   ToText()    const		{ return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToDeclaration()391 	TiXmlDeclaration* ToDeclaration() const	{ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
392 
393 	virtual TiXmlNode* Clone() const = 0;
394 
395 	// The real work of the input operator.
396 	virtual void StreamIn( std::istream* in, std::string* tag ) = 0;
397 
398   protected:
399 	TiXmlNode( NodeType type );
400 
401 	// The node is passed in by ownership. This object will delete it.
402 	TiXmlNode* LinkEndChild( TiXmlNode* addThis );
403 
404 	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
405 	TiXmlNode* Identify( const char* start );
406 
CopyToClone(TiXmlNode * target)407 	void CopyToClone( TiXmlNode* target ) const	{ target->value = value; }
408 
409 	TiXmlNode*		parent;
410 	NodeType		type;
411 
412 	TiXmlNode*		firstChild;
413 	TiXmlNode*		lastChild;
414 
415 	std::string		value;
416 
417 	TiXmlNode*		prev;
418 	TiXmlNode*		next;
419 };
420 
421 
422 /** An attribute is a name-value pair. Elements have an arbitrary
423 	number of attributes, each with a unique name.
424 
425 	@note The attributes are not TiXmlNodes, since they are not
426 		  part of the tinyXML document object model. There are other
427 		  suggested ways to look at this problem.
428 
429 	@note Attributes have a parent
430 */
431 class TiXmlAttribute : public TiXmlBase
432 {
433 	friend class TiXmlAttributeSet;
434 
435   public:
436 	/// Construct an empty attribute.
TiXmlAttribute()437 	TiXmlAttribute() : prev( 0 ), next( 0 )	{}
438 
439 	/// Construct an attribute with a name and value.
TiXmlAttribute(const std::string & _name,const std::string & _value)440 	TiXmlAttribute( const std::string& _name, const std::string& _value )	: name( _name ), value( _value ), prev( 0 ), next( 0 ) {}
441 
Name()442 	const std::string& Name()  const { return name; }		///< Return the name of this attribute.
443 
Value()444 	const std::string& Value() const { return value; }		///< Return the value of this attribute.
445 	const int          IntValue() const;					///< Return the value of this attribute, converted to an integer.
446 	const double	   DoubleValue() const;					///< Return the value of this attribute, converted to a double.
447 
SetName(const std::string & _name)448 	void SetName( const std::string& _name )	{ name = _name; }		///< Set the name of this attribute.
SetValue(const std::string & _value)449 	void SetValue( const std::string& _value )	{ value = _value; }		///< Set the value.
450 	void SetIntValue( int value );										///< Set the value from an integer.
451 	void SetDoubleValue( double value );								///< Set the value from a double.
452 
453 	/// Get the next sibling attribute in the DOM. Returns null at end.
454 	TiXmlAttribute* Next() const;
455 	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
456 	TiXmlAttribute* Previous() const;
457 
458 	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
459 	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
460 	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
461 
462 	/*	[internal use]
463 		Attribtue parsing starts: first letter of the name
464 						 returns: the next char after the value end quote
465 	*/
466 	virtual const char* Parse( const char* p );
467 
468 	// [internal use]
469  	virtual void Print( FILE* cfile, int depth ) const;
470 
471 	// [internal use]
472 	virtual void StreamOut( std::ostream* out ) const;
473 
474 	// [internal use]
475 	// Set the document pointer so the attribute can report errors.
SetDocument(TiXmlDocument * doc)476 	void SetDocument( TiXmlDocument* doc )	{ document = doc; }
477 
478   private:
479 	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
480 	std::string		name;
481 	std::string		value;
482 
483 	TiXmlAttribute*	prev;
484 	TiXmlAttribute*	next;
485 };
486 
487 
488 /*	A class used to manage a group of attributes.
489 	It is only used internally, both by the ELEMENT and the DECLARATION.
490 
491 	The set can be changed transparent to the Element and Declaration
492 	classes that use it, but NOT transparent to the Attribute
493 	which has to implement a next() and previous() method. Which makes
494 	it a bit problematic and prevents the use of STL.
495 
496 	This version is implemented with circular lists because:
497 		- I like circular lists
498 		- it demonstrates some independence from the (typical) doubly linked list.
499 */
500 class TiXmlAttributeSet
501 {
502   public:
503 	TiXmlAttributeSet();
504 	~TiXmlAttributeSet();
505 
506 	void Add( TiXmlAttribute* attribute );
507 	void Remove( TiXmlAttribute* attribute );
508 
First()509 	TiXmlAttribute* First() const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
Last()510 	TiXmlAttribute* Last()  const	{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
511 
512 	TiXmlAttribute*	Find( const std::string& name ) const;
513 
514   private:
515 	TiXmlAttribute sentinel;
516 };
517 
518 
519 /** The element is a container class. It has a value, the element name,
520 	and can contain other elements, text, comments, and unknowns.
521 	Elements also contain an arbitrary number of attributes.
522 */
523 class TiXmlElement : public TiXmlNode
524 {
525   public:
526 	/// Construct an element.
527 	TiXmlElement( const std::string& value );
528 
529 	virtual ~TiXmlElement();
530 
531 	/** Given an attribute name, attribute returns the value
532 		for the attribute of that name, or null if none exists.
533 	*/
534 	const std::string* Attribute( const std::string& name ) const;
535 
536 	/** Given an attribute name, attribute returns the value
537 		for the attribute of that name, or null if none exists.
538 	*/
539 	const std::string* Attribute( const std::string& name, int* i ) const;
540 
541 	/** Sets an attribute of name to a given value. The attribute
542 		will be created if it does not exist, or changed if it does.
543 	*/
544 	void SetAttribute( const std::string& name,
545 					   const std::string& value );
546 
547 	/** Sets an attribute of name to a given value. The attribute
548 		will be created if it does not exist, or changed if it does.
549 	*/
550 	void SetAttribute( const std::string& name,
551 					   int value );
552 
553 	/** Deletes an attribute with the given name.
554 	*/
555 	void RemoveAttribute( const std::string& name );
556 
FirstAttribute()557 	TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
LastAttribute()558 	TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
559 
560 	// [internal use] Creates a new Element and returs it.
561 	virtual TiXmlNode* Clone() const;
562 	// [internal use]
563  	virtual void Print( FILE* cfile, int depth ) const;
564 	// [internal use]
565 	virtual void StreamOut ( std::ostream* out ) const;
566 	// [internal use]
567 	virtual void StreamIn( std::istream* in, std::string* tag );
568 
569   protected:
570 	/*	[internal use]
571 		Attribtue parsing starts: next char past '<'
572 						 returns: next char past '>'
573 	*/
574 	virtual const char* Parse( const char* p );
575 
576 	/*	[internal use]
577 		Reads the "value" of the element -- another element, or text.
578 		This should terminate with the current end tag.
579 	*/
580 	const char* ReadValue( const char* in );
581 	bool ReadValue( std::istream* in );
582 
583   private:
584 	TiXmlAttributeSet attributeSet;
585 };
586 
587 
588 /**	An XML comment.
589 */
590 class TiXmlComment : public TiXmlNode
591 {
592   public:
593 	/// Constructs an empty comment.
TiXmlComment()594 	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
~TiXmlComment()595 	virtual ~TiXmlComment()	{}
596 
597 	// [internal use] Creates a new Element and returs it.
598 	virtual TiXmlNode* Clone() const;
599 	// [internal use]
600  	virtual void Print( FILE* cfile, int depth ) const;
601 	// [internal use]
602 	virtual void StreamOut ( std::ostream* out ) const;
603 	// [internal use]
604 	virtual void StreamIn( std::istream* in, std::string* tag );
605 
606   protected:
607 	/*	[internal use]
608 		Attribtue parsing starts: at the ! of the !--
609 						 returns: next char past '>'
610 	*/
611 	virtual const char* Parse( const char* p );
612 };
613 
614 
615 /** XML text. Contained in an element.
616 */
617 class TiXmlText : public TiXmlNode
618 {
619   public:
TiXmlText(const std::string & initValue)620 	TiXmlText( const std::string& initValue )  : TiXmlNode( TiXmlNode::TEXT ) { SetValue( initValue ); }
~TiXmlText()621 	virtual ~TiXmlText() {}
622 
623 
624 	// [internal use] Creates a new Element and returns it.
625 	virtual TiXmlNode* Clone() const;
626 	// [internal use]
627  	virtual void Print( FILE* cfile, int depth ) const;
628 	// [internal use]
629 	virtual void StreamOut ( std::ostream* out ) const;
630 	// [internal use]
631 	bool Blank() const;	// returns true if all white space and new lines
632 	/*	[internal use]
633 		Attribtue parsing starts: First char of the text
634 						 returns: next char past '>'
635 	*/
636 	virtual const char* Parse( const char* p );
637 	// [internal use]
638 	virtual void StreamIn( std::istream* in, std::string* tag );
639 };
640 
641 
642 /** In correct XML the declaration is the first entry in the file.
643 	@verbatim
644 		<?xml version="1.0" standalone="yes"?>
645 	@endverbatim
646 
647 	TinyXml will happily read or write files without a declaration,
648 	however. There are 3 possible attributes to the declaration:
649 	version, encoding, and standalone.
650 
651 	Note: In this version of the code, the attributes are
652 	handled as special cases, not generic attributes, simply
653 	because there can only be at most 3 and they are always the same.
654 */
655 class TiXmlDeclaration : public TiXmlNode
656 {
657   public:
658 	/// Construct an empty declaration.
TiXmlDeclaration()659 	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
660 
661 	/// Construct.
662 	TiXmlDeclaration( const std::string& version,
663 					  const std::string& encoding,
664 					  const std::string& standalone );
665 
~TiXmlDeclaration()666 	virtual ~TiXmlDeclaration()	{}
667 
668 	/// Version. Will return empty if none was found.
Version()669 	const std::string& Version() const		{ return version; }
670 	/// Encoding. Will return empty if none was found.
Encoding()671 	const std::string& Encoding() const		{ return encoding; }
672 	/// Is this a standalone document?
Standalone()673 	const std::string& Standalone() const		{ return standalone; }
674 
675 	// [internal use] Creates a new Element and returs it.
676 	virtual TiXmlNode* Clone() const;
677 	// [internal use]
678  	virtual void Print( FILE* cfile, int depth ) const;
679 	// [internal use]
680 	virtual void StreamOut ( std::ostream* out ) const;
681 	// [internal use]
682 	virtual void StreamIn( std::istream* in, std::string* tag );
683 
684   protected:
685 	//	[internal use]
686 	//	Attribtue parsing starts: next char past '<'
687 	//					 returns: next char past '>'
688 
689 	virtual const char* Parse( const char* p );
690 
691   private:
692 	std::string version;
693 	std::string encoding;
694 	std::string standalone;
695 };
696 
697 
698 /** Any tag that tinyXml doesn't recognize is save as an
699 	unknown. It is a tag of text, but should not be modified.
700 	It will be written back to the XML, unchanged, when the file
701 	is saved.
702 */
703 class TiXmlUnknown : public TiXmlNode
704 {
705   public:
TiXmlUnknown()706 	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
~TiXmlUnknown()707 	virtual ~TiXmlUnknown() {}
708 
709 	// [internal use]
710 	virtual TiXmlNode* Clone() const;
711 	// [internal use]
712  	virtual void Print( FILE* cfile, int depth ) const;
713 	// [internal use]
714 	virtual void StreamOut ( std::ostream* out ) const;
715 	// [internal use]
716 	virtual void StreamIn( std::istream* in, std::string* tag );
717 
718   protected:
719 	/*	[internal use]
720 		Attribute parsing starts: First char of the text
721 						 returns: next char past '>'
722 	*/
723 	virtual const char* Parse( const char* p );
724 };
725 
726 
727 /** Always the top level node. A document binds together all the
728 	XML pieces. It can be saved, loaded, and printed to the screen.
729 	The 'value' of a document node is the xml file name.
730 */
731 class TiXmlDocument : public TiXmlNode
732 {
733   public:
734 	/// Create an empty document, that has no name.
735 	TiXmlDocument();
736 	/// Create a document with a name. The name of the document is also the filename of the xml.
737 	TiXmlDocument( const std::string& documentName );
738 
~TiXmlDocument()739 	virtual ~TiXmlDocument() {}
740 
741 	/** Load a file using the current document value.
742 		Returns true if successful. Will delete any existing
743 		document data before loading.
744 	*/
745 	bool LoadFile();
746 	/// Save a file using the current document value. Returns true if successful.
747 	bool SaveFile() const;
748 	/// Load a file using the given filename. Returns true if successful.
749 	bool LoadFile( const std::string& filename );
750 	/// Save a file using the given filename. Returns true if successful.
751 	bool SaveFile( const std::string& filename ) const;
752 
753 	/// Parse the given null terminated block of xml data.
754 	virtual const char* Parse( const char* p );
755 
756 	/** Get the root element -- the only top level element -- of the document.
757 		In well formed XML, there should only be one. TinyXml is tolerant of
758 		multiple elements at the document level.
759 	*/
RootElement()760 	TiXmlElement* RootElement() const		{ return FirstChildElement(); }
761 
762 	/// If, during parsing, a error occurs, Error will be set to true.
Error()763 	bool Error() const						{ return error; }
764 
765 	/// Contains a textual (english) description of the error if one occurs.
ErrorDesc()766 	const std::string& ErrorDesc() const	{ return errorDesc; }
767 
768 	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
769 		prefer the ErrorId, this function will fetch it.
770 	*/
ErrorId()771 	const int ErrorId()	const				{ return errorId; }
772 
773 	/// If you have handled the error, it can be reset with this call.
ClearError()774 	void ClearError()						{ error = false; errorId = 0; errorDesc = ""; }
775 
776 	/** Dump the document to standard out. */
Print()777 	void Print() const								{ Print( stdout, 0 ); }
778 
779 	// [internal use]
780  	virtual void Print( FILE* cfile, int depth = 0 ) const;
781 	// [internal use]
782 	virtual void StreamOut ( std::ostream* out ) const;
783 	// [internal use]
784 	virtual TiXmlNode* Clone() const;
785 	// [internal use]
SetError(int err)786 	void SetError( int err ) {		assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
787 									error   = true;
788 									errorId = err;
789 									errorDesc = errorString[ errorId ]; }
790 	// [internal use]
791 	virtual void StreamIn( std::istream* in, std::string* tag );
792 
793   protected:
794 
795   private:
796 	bool error;
797 	int  errorId;
798 	std::string errorDesc;
799 };
800 
801 
802 
803 #endif
804 
805