1 /*
2 http://code.google.com/p/ticpp/
3 Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 /**
24 @copydoc ticpp
25 @file
26 @author		Ryan Pusztai
27 @author		Ryan Mulder
28 @date		04/11/2006
29 
30 @version	0.04a by edam@waxworlds.org: based Exception based on std::exception; added stream
31 					<< and >> support; added Document::Parse(); bug fix; improved THROW() macro.
32 @version	0.04 Added NodeImp class. Also made all the classes inherit from NodeImp.
33 @version	0.03 Added Declaration class
34 @version	0.02 Added Element class
35 @version	0.01 Added Exception class, Document class
36 
37 @todo add UNKNOWN support. See ticpp::NodeFactory.
38 @todo add TYPECOUNT support. See ticpp::NodeFactory.
39 @todo Add a quick reference
40 */
41 
42  /*
43  * THIS FILE WAS ALTERED BY Matt Janisz, 12. October 2012.
44  *
45  * - added ticppapi.h include and TICPP_API dll-interface to support building DLL using VS200X
46  */
47 
48 #ifndef TIXML_USE_TICPP
49 	#define TIXML_USE_TICPP
50 #endif
51 
52 #ifndef TICPP_INCLUDED
53 #define TICPP_INCLUDED
54 
55 #include "ticppapi.h"
56 #include "tinyxml.h"
57 #include <sstream>
58 #include <vector>
59 #include <memory>
60 #include <exception>
61 #include <typeinfo>
62 
63 /**
64 @subpage ticpp is a TinyXML wrapper that uses a lot more C++ ideals.
65 It throws exceptions, uses templates, is in its own name space, and
66 <b>requires</b> STL (Standard Template Library). This is done to ease the use
67 of getting values in and out of the xml.
68 
69 If you don't perfer to use some of the concepts just don't use it.
70 It is just a wrapper that extends TinyXML. It doesn't actually change
71 any of TinyXML.
72 */
73 namespace ticpp
74 {
75     /**
76 	This is a ticpp exception class
77 	*/
78 	class TICPP_API Exception : public std::exception
79 	{
80 	public:
81 		/**
82 		Construct an exception with a message
83 		*/
84 		Exception( const std::string& details );
85 		~Exception() throw();
86 
87 		/// Override std::exception::what() to return m_details
88 		const char* what() const throw();
89 
90 		std::string m_details; /**< Exception Details */
91 	};
92 
93 	/**
94 	This allows you to stream your exceptions in.
95 	It will take care of the conversion	and throwing the exception.
96 	*/
97 	#define TICPPTHROW( message ) 											\
98 	{																		\
99 		std::ostringstream full_message;									\
100 		std::string file( __FILE__ );										\
101 		file = file.substr( file.find_last_of( "\\/" ) + 1 );				\
102 		full_message << message << " <" << file << "@" << __LINE__ << ">";	\
103 		full_message << BuildDetailedErrorString();							\
104 		throw Exception( full_message.str() );								\
105 	}
106 
107 	// Forward Declarations for Visitor, and others.
108 	class TICPP_API Document;
109 	class TICPP_API Element;
110 	class TICPP_API Declaration;
111 	class TICPP_API StylesheetReference;
112 	class TICPP_API Text;
113 	class TICPP_API Comment;
114 	class TICPP_API Attribute;
115 
116 	/** Wrapper around TiXmlVisitor */
117 	class TICPP_API Visitor : public TiXmlVisitor
118 	{
119 	public:
120 		// Overload the TiXmlVisitor functions, wrap objects, call ticpp::Visitor functions
121 		/// @internal
122 		virtual bool VisitEnter( const TiXmlDocument& doc );
123 		/// @internal
124 		virtual bool VisitExit( const TiXmlDocument& doc );
125 		/// @internal
126 		virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
127 		/// @internal
128 		virtual bool VisitExit( const TiXmlElement& element );
129 		/// @internal
130 		virtual bool Visit( const TiXmlDeclaration& declaration );
131 		/// @internal
132 		virtual bool Visit( const TiXmlStylesheetReference& stylesheet );
133 		/// @internal
134 		virtual bool Visit( const TiXmlText& text );
135 		/// @internal
136 		virtual bool Visit( const TiXmlComment& comment );
137 
138 	public:
139 		/// Visit a document.
VisitEnter(const Document &)140 		virtual bool VisitEnter( const Document& /*doc*/ )			{ return true; }
141 		/// Visit a document.
VisitExit(const Document &)142 		virtual bool VisitExit( const Document& /*doc*/ )			{ return true; }
143 
144 		/// Visit an element.
VisitEnter(const Element &,const Attribute *)145 		virtual bool VisitEnter( const Element& /*element*/, const Attribute* /*firstAttribute*/ )	{ return true; }
146 		/// Visit an element.
VisitExit(const Element &)147 		virtual bool VisitExit( const Element& /*element*/ )		{ return true; }
148 
149 		/// Visit a declaration
Visit(const Declaration &)150 		virtual bool Visit( const Declaration& /*declaration*/ )	{ return true; }
151 		/// Visit a stylesheet reference
Visit(const StylesheetReference &)152 		virtual bool Visit( const StylesheetReference& /*stylesheet*/ )	{ return true; }
153 		/// Visit a text node
Visit(const Text &)154 		virtual bool Visit( const Text& /*text*/ )					{ return true; }
155 		/// Visit a comment node
Visit(const Comment &)156 		virtual bool Visit( const Comment& /*comment*/ )			{ return true; }
157 	};
158 
159 	/** Wrapper around TiXmlBase */
160 	class TICPP_API Base
161 	{
162 	public:
163 
164 		/**
165 		Converts any class with a proper overload of the << opertor to a std::string
166 		@param value The value to be converted
167 		@throws Exception When value cannot be converted to a std::string
168 		*/
169 		template < class T >
ToString(const T & value)170 			std::string ToString( const T& value ) const
171 		{
172 			std::stringstream convert;
173 			convert << value;
174 			if ( convert.fail() )
175 			{
176 				TICPPTHROW( "Could not convert value to text" );
177 			}
178 			return convert.str();
179 		}
180 
ToString(const std::string & value)181 		std::string ToString( const std::string& value ) const
182 		{
183 			return value;
184 		}
185 
186 		/**
187 		Converts a std::string to any class with a proper overload of the >> opertor
188 		@param temp			The string to be converted
189 		@param out	[OUT]	The container for the returned value
190 		@throws Exception When temp cannot be converted to the target type
191 		*/
192 		template < class T >
FromString(const std::string & temp,T * out)193 			void FromString( const std::string& temp, T* out ) const
194 		{
195 			std::istringstream val( temp );
196 			val >> *out;
197 
198 			if ( val.fail() )
199 			{
200 				TICPPTHROW( "Could not convert \"" << temp << "\" to target type" );
201 			}
202 		}
203 
204 		/**
205 		Specialization for std::string
206 		*/
FromString(const std::string & temp,std::string * out)207 		void FromString( const std::string& temp, std::string* out ) const
208 		{
209 			*out = temp;
210 		}
211 
212 		/**
213 		Return the position, in the original source file, of this node or attribute.
214 		Wrapper around TiXmlBase::Row()
215 		*/
Row()216 		int Row() const
217 		{
218 			return GetBasePointer()->Row();
219 		}
220 
221 		/**
222 		Return the position, in the original source file, of this node or attribute.
223 		Wrapper around TiXmlBase::Row()
224 		*/
Column()225 		int Column() const
226 		{
227 			return GetBasePointer()->Column();
228 		}
229 
230 		/**
231 		Compare internal TiXml pointers to determine is both are wrappers around the same node
232 		*/
233 		bool operator == ( const Base& rhs ) const
234 		{
235 			return ( GetBasePointer() == rhs.GetBasePointer() );
236 		}
237 
238 		/**
239 		Compare internal TiXml pointers to determine is both are wrappers around the same node
240 		*/
241 		bool operator != ( const Base& rhs ) const
242 		{
243 			return ( GetBasePointer() != rhs.GetBasePointer() );
244 		}
245 
246 		/**
247 		Builds detailed error string using TiXmlDocument::Error() and others
248 		*/
BuildDetailedErrorString()249 		std::string BuildDetailedErrorString() const
250 		{
251 			std::ostringstream full_message;
252 			#ifndef TICPP_NO_RTTI
253 			TiXmlNode* node = dynamic_cast< TiXmlNode* >( GetBasePointer() );
254 			if ( node != 0 )
255 			{
256 				TiXmlDocument* doc = node->GetDocument();
257 				if ( doc != 0 )
258 				{
259 					if ( doc->Error() )
260 					{
261 						full_message 	<< "\nDescription: " << doc->ErrorDesc()
262 										<< "\nFile: " << (strlen( doc->Value() ) > 0 ? doc->Value() : "<unnamed-file>")
263 										<< "\nLine: " << doc->ErrorRow()
264 										<< "\nColumn: " << doc->ErrorCol();
265 					}
266 				}
267 			}
268 			#endif
269 			return full_message.str();
270 		}
271 
272 		/**
273 		Destructor
274 		*/
~Base()275 		virtual ~Base()
276 		{
277 		}
278 
279 	protected:
280 		mutable TiCppRCImp* m_impRC;	/**< Holds status of internal TiXmlPointer - use this to determine if object has been deleted already */
281 
282 		/**
283 		@internal
284 		Updates the pointer to the reference counter to point at the counter in the new node.
285 
286 		@param node TiXmlBase containing the new reference counter
287 		*/
SetImpRC(TiXmlBase * node)288 		void SetImpRC( TiXmlBase* node )
289 		{
290 			m_impRC = node->m_tiRC;
291 		}
292 
ValidatePointer()293 		void ValidatePointer() const
294 		{
295 			if ( m_impRC->IsNull() )
296 			{
297 				TICPPTHROW( "Internal TiXml Pointer is NULL" );
298 			}
299 		}
300 
301 		/**
302 		@internal
303 		Get internal TiXmlBase*
304 		*/
305 		virtual TiXmlBase* GetBasePointer() const = 0;
306 	};
307 
308 	/**
309 	Wrapper around TiXmlAttribute
310 	*/
311 	class TICPP_API Attribute : public Base
312 	{
313 	private:
314 		TiXmlAttribute* m_tiXmlPointer;
GetBasePointer()315 		TiXmlBase* GetBasePointer() const
316 		{
317 			ValidatePointer();
318 			return m_tiXmlPointer;
319 		}
320 
321 	public:
322 		/**
323 		Construct an empty attribute.
324 		*/
325 		Attribute();
326 
327 		/**
328 		Construct an attribute with @a name and @a value
329 
330 		@param name The name of the attribute
331 		@param value The value of the attribute
332 		*/
333 		Attribute( const std::string& name, const std::string& value );
334 
335 		/**
336 		@internal
337 		Construct an attribute with the internal pointer
338 
339 		@param attribute The internal pointer
340 		*/
341 		Attribute( TiXmlAttribute* attribute );
342 
343 		/**
344 		Get the value of this attribute
345 		Uses Base::FromString to convert TiXmlAttribute::ValueStr from a std::string,
346 		and puts it in the passed pointer.
347 
348 		@param value [OUT] A pointer to fill with the value
349 		*/
350 		template < class T >
GetValue(T * value)351 			void GetValue( T* value ) const
352 		{
353 			ValidatePointer();
354 			FromString( m_tiXmlPointer->ValueStr(), value );
355 		}
356 
357 		/**
358 		Get the value of this attribute.
359 		Simple wrapper for TiXmlAttribute::ValueStr.
360 
361 		@see GetValue
362 		*/
363 		std::string Value() const;
364 
365 		/**
366 		Set the value of this node.
367 		Uses Base::ToString to convert value to a std::string, then calls TiXmlAttribute::SetValue.
368 
369 		@param value The value to set
370 		*/
371 		template < class T >
SetValue(const T & value)372 			void SetValue( const T& value )
373 		{
374 			ValidatePointer();
375 			m_tiXmlPointer->SetValue( ToString( value ) );
376 		}
377 
378 		/**
379 		Get the value of this attribute
380 		Uses Base::FromString to convert TiXmlAttribute::Name from a std::string,
381 		and puts it in the passed pointer.
382 
383 		@param name [OUT] A pointer to fill with the name
384 		*/
385 		template < class T >
GetName(T * name)386 			void GetName( T* name ) const
387 		{
388 			ValidatePointer();
389 			FromString( m_tiXmlPointer->Name(), name );
390 		}
391 
392 		/**
393 		Get the value of this attribute.
394 		Simple wrapper for TiXmlAttribute::Name.
395 
396 		@see GetName
397 		*/
398 		std::string Name() const;
399 
400 		/**
401 		Set the value of this attribute.
402 		Uses Base::ToString to convert @a name to a std::string, then calls TiXmlAttribute::SetName.
403 
404 		@param name The name to set
405 		*/
406 		template < class T >
SetName(const T & name)407 			void SetName( const T& name )
408 		{
409 			ValidatePointer();
410 			m_tiXmlPointer->SetName( ToString( name ) );
411 		}
412 
413 		/**
414 		@internal
415 		Updates the reference count for the old and new pointers.
416 		*/
417 		void operator=( const Attribute& copy );
418 
419 		/**
420 		@internal
421 		Updates the reference count for the old and new pointers.
422 		*/
423 		Attribute( const Attribute& copy );
424 
425 		/*
426 		Decrements reference count.
427 		*/
428 		~Attribute();
429 
430 		/**
431 		Get the next sibling attribute in the DOM.
432 		*/
433 		Attribute* Next( bool throwIfNoAttribute = true ) const;
434 
435 		/**
436 		Get the previous sibling attribute in the DOM.
437 		*/
438 		Attribute* Previous( bool throwIfNoAttribute = true ) const;
439 
440 		/**
441 		@internal
442 		Just for Iterator<>
443 
444 		@param next [OUT] The pointer to the next valid attribute
445 		@return true if there is a next attribute, false if not
446 		*/
447 		void IterateNext( const std::string&, Attribute** next ) const;
448 
449 		/**
450 		@internal
451 		Just for Iterator<>
452 
453 		@param previous [OUT] The pointer to the previous valid attribute
454 		@return true if there is a previous attribute, false if not
455 		*/
456 		void IteratePrevious( const std::string&, Attribute** previous ) const;
457 
458 		/**
459 		All TinyXml classes can print themselves to a filestream.
460 		*/
461 		virtual void Print( FILE* file, int depth ) const;
462 
463 	private:
464 
465 		/**
466 		@internal
467 		Sets the internal pointer.
468 		Saves a copy of the pointer to the RC object.
469 
470 		@param newPointer TiXmlAttribute* to set.
471 		*/
472 		void SetTiXmlPointer( TiXmlAttribute* newPointer );
473 	};
474 
475 	/**
476 	Wrapper around TiXmlNode
477 	*/
478 	class TICPP_API Node : public Base
479 	{
480 	public:
481 
482 		/**
483 		Get the value of this node
484 		Uses Base::FromString to convert TiXmlNode::ValueStr from a std::string,
485 		and puts it in the passed pointer.
486 
487 		@param value [OUT] A pointer to fill with the value
488 		*/
489 		template < class T >
GetValue(T * value)490 			void GetValue( T* value) const
491 		{
492 			FromString( GetTiXmlPointer()->ValueStr(), value );
493 		}
494 
495 		/**
496 		Get the value of this node.
497 		Simple wrapper for TiXmlNode::ValueStr.
498 
499 		@see GetValue
500 		*/
501 		std::string Value() const;
502 
503 		/**
504 		Set the value of this node.
505 		Uses Base::ToString to convert value to a std::string, then calls TiXmlNode::SetValue.
506 
507 		@param value The value to set
508 		*/
509 		template < class T >
SetValue(const T & value)510 			void SetValue( const T& value )
511 		{
512 			GetTiXmlPointer()->SetValue( ToString( value ) );
513 		}
514 
515 		/**
516 		Clear all Nodes below this.
517 		Simple wrapper for TiXmlNode::Clear.
518 		*/
519 		void Clear();
520 
521 		/**
522 		The Parent of this Node.
523 		Simple wrapper for TiXmlNode::Parent.
524 
525 		@param throwIfNoParent [DEF] If true, throws when Parent = NULL.
526 		@return The parent of this node, NULL if there is no Parent.
527 		@throws Exception When throwIfNoParent is true, and TiXmlNode::Parent returns Null.
528 		*/
529 		Node* Parent( bool throwIfNoParent = true ) const;
530 
531 		/**
532 		The first child of this node.
533 
534 		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no children.
535 		@return Pointer to child, Null if no children and 'throwIfNoChildren' is false.
536 		@throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChild returns Null.
537 
538 		@see TiXmlNode::FirstChild
539 		*/
540 		Node* FirstChild( bool throwIfNoChildren = true ) const;
541 
542 		/**
543 		@internal
544 		The first child of this node with the matching @a value.
545 
546 		@overload
547 		@param value				Value to match.
548 		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
549 
550 		@see FirstChild( bool throwIfNoChildren = true )
551 		*/
552 		Node* FirstChild( const char* value, bool throwIfNoChildren = true ) const;
553 
554 		/**
555 		The first child of this node with the matching @a value.
556 
557 		@overload
558 		@param value				Value to match.
559 		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
560 
561 		@see FirstChild( const char* value, bool throwIfNoChildren = true )
562 		*/
563 		Node* FirstChild( const std::string& value, bool throwIfNoChildren = true ) const;
564 
565 		/**
566 		The last child of this node.
567 
568 		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no children.
569 		@return Pointer to child, Null if no children and 'throwIfNoChildren' is false.
570 		@throws Exception When throwIfNoChildren is true, and TiXmlNode::LastChild returns Null.
571 
572 		@see TiXmlNode::LastChild
573 		*/
574 		Node* LastChild( bool throwIfNoChildren = true ) const;
575 
576 		/**
577 		@internal
578 		The last child of this node with the matching @a value.
579 
580 		@overload
581 		@param value				Value to match.
582 		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
583 
584 		@see LastChild( bool throwIfNoChildren = true )
585 		*/
586 		Node* LastChild( const char* value, bool throwIfNoChildren = true ) const;
587 
588 		/**
589 		The last child of this node with the matching @a value.
590 
591 		@overload
592 		@param value				Value to match.
593 		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
594 
595 		@see LastChild( const char* value, bool throwIfNoChildren = true )
596 		*/
597 		Node* LastChild( const std::string& value, bool throwIfNoChildren = true ) const;
598 
599 		/**
600 		An alternate way to walk the children of a node.
601 		Simple wrapper for TiXmlNode::IterateChildren.
602 
603 		@param previous The previous Node* that was returned from IterateChildren.
604 		@return NULL When there are no more children.
605 		*/
606 		Node* IterateChildren( Node* previous ) const;
607 
608 		/**
609 		This flavor of IterateChildren searches for children with a particular @a value.
610 		Simple wrapper for TiXmlNode::IterateChildren.
611 
612 		@param value	The value you want to search for.
613 		@param previous The previous Node* that was returned from IterateChildren.
614 		@return NULL When there are no more children.
615 		*/
616 		Node* IterateChildren( const std::string& value, Node* previous ) const;
617 
618 		/**
619 		Adds a child past the LastChild.
620 		Throws if you try to insert a document.
621 
622 		@note This takes a copy of @a addThis so it is not as efficiant as LinkEndChild.
623 		@param addThis Node to insert.
624 		@throws Exception When TiXmlNode::InsertEndChild returns Null
625 
626 		@see LinkEndChild
627 		@see TiXmlNode::InsertEndChild
628 		*/
629 		Node* InsertEndChild( const Node& addThis );
630 
631 		/**
632 		Adds a child past the LastChild.
633 		Throws if you try to link a document.
634 
635 		@param childNode Node to link.
636 		@throws Exception When TiXmlNode::LinkEndChild returns Null.
637 
638 		@see InsertEndChild
639 		@see TiXmlNode::LinkEndChild
640 		*/
641 		Node* LinkEndChild( Node* childNode );
642 
643 		/**
644 		Adds a child before the specified child.
645 		Throws if you try to insert a document.
646 
647 		@param beforeThis	Node that will have @a addThis linked before.
648 		@param addThis		Node to insert before.
649 		@throws Exception When TiXmlNode::InsertBeforeChild returns Null.
650 
651 		@see InsertAfterChild
652 		@see TiXmlNode::InsertBeforeChild
653 		*/
654 		Node* InsertBeforeChild( Node* beforeThis, const Node& addThis );
655 
656 		/**
657 		Adds a child after the specified child.
658 		Throws if you try to insert a document.
659 
660 		@param afterThis	Node that will have @a addThis linked after.
661 		@param addThis		Node to insert after.
662 		@throws Exception When TiXmlNode::InsertAfterChild returns Null.
663 
664 		@see InsertBeforeChild
665 		@see TiXmlNode::InsertAfterChild
666 		*/
667 		Node* InsertAfterChild( Node* afterThis, const Node& addThis );
668 
669 		/**
670 		Replace a child of this node.
671 		Throws if you try to replace with a document.
672 
673 		@param replaceThis	Node to replace.
674 		@param withThis		Node that is replacing @a replaceThis.
675 		@throws Exception When TiXmlNode::ReplaceChild returns Null.
676 
677 		@see TiXmlNode::ReplaceChild
678 		*/
679 		Node* ReplaceChild( Node* replaceThis, const Node& withThis );
680 
681 		/**
682 		Delete a child of this node.
683 
684 		@param removeThis Node to delete.
685 		@throws Exception When removeThis is not a child of this Node.
686 
687 		@see TiXmlNode::RemoveChild
688 		*/
689 		void RemoveChild( Node* removeThis );
690 
691 		/**
692 		Navigate to a sibling node.
693 		Wrapper around TiXmlNode::PreviousSibling.
694 
695 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
696 		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
697 		@throws Exception When TiXmlNode::PreviousSibling returns Null and 'throwIfNoSiblings' is true.
698 		*/
699 		Node* PreviousSibling( bool throwIfNoSiblings = true ) const;
700 
701 		/**
702 		Navigate to a sibling node with the given @a value.
703 
704 		@overload
705 		@param value The value of the node to look for.
706 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
707 
708 		@see PreviousSibling( bool throwIfNoSiblings )
709 		*/
710 		Node* PreviousSibling( const std::string& value, bool throwIfNoSiblings = true ) const;
711 
712 		/**
713 		@internal
714 		Navigate to a sibling node with the given @a value.
715 
716 		@overload
717 		@param value The value of the node to look for.
718 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
719 
720 		@see PreviousSibling( const std::string& value, bool throwIfNoSiblings )
721 		*/
722 		Node* PreviousSibling( const char* value, bool throwIfNoSiblings = true ) const;
723 
724 		/**
725 		Navigate to a sibling node.
726 		Wrapper around TiXmlNode::NextSibling.
727 
728 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
729 		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
730 		@throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true.
731 		*/
732 		Node* NextSibling( bool throwIfNoSiblings = true ) const;
733 
734 		/**
735 		Navigate to a sibling node with the given @a value.
736 
737 		@overload
738 		@param value The value of the node to look for.
739 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
740 
741 		@see NextSibling( bool throwIfNoSiblings )
742 		*/
743 		Node* NextSibling( const std::string& value, bool throwIfNoSiblings = true ) const;
744 
745 		/**
746 		@internal
747 		Navigate to a sibling node with the given @a value.
748 
749 		@overload
750 		@param value The value of the node to look for.
751 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
752 
753 		@see NextSibling( const std::string& value, bool throwIfNoSiblings )
754 		*/
755 		Node* NextSibling( const char* value, bool throwIfNoSiblings = true ) const;
756 
757 		/**
758 		@internal
759 		Just for Iterator<>
760 
761 		@param value The value of nodes to iterate through
762 		@param next [OUT] The pointer to the first valid node
763 		*/
764 		template < class T >
IterateFirst(const std::string & value,T ** first)765 			void IterateFirst( const std::string& value, T** first ) const
766 		{
767 			*first = 0;
768 			for( Node* child = FirstChild( value, false ); child; child = child->NextSibling( value, false ) )
769 			{
770 				*first = dynamic_cast< T* >( child );
771 				if ( 0 != *first )
772 				{
773 					return;
774 				}
775 			}
776 		}
777 
IterateFirst(const std::string &,Attribute **)778 		virtual	void IterateFirst( const std::string&, Attribute** ) const
779 		{
780 			TICPPTHROW( "Attributes can only be iterated with Elements." )
781 		}
782 
783 		/**
784 		@internal
785 		Just for Iterator<>
786 
787 		@param value The value of nodes to iterate through
788 		@param next [OUT] The pointer to the next valid node
789 		*/
790 		template < class T >
IterateNext(const std::string & value,T ** next)791 			void IterateNext( const std::string& value, T** next ) const
792 		{
793 			Node* sibling = NextSibling( value, false );
794 			*next = dynamic_cast< T* >( sibling );
795 
796 			while ( ( 0 != sibling ) && ( 0 == *next ) )
797 			{
798 				sibling = sibling->NextSibling( value, false );
799 				*next = dynamic_cast< T* >( sibling );
800 			}
801 		}
802 
803 		/**
804 		@internal
805 		Just for Iterator<>
806 
807 		@param value The value of nodes to iterate through
808 		@param previous [OUT] The pointer to the previous valid node
809 		*/
810 		template < class T >
IteratePrevious(const std::string & value,T ** previous)811 			void IteratePrevious( const std::string& value, T** previous  ) const
812 		{
813 			Node* sibling = PreviousSibling( value, false );
814 			*previous = dynamic_cast< T* >( sibling );
815 
816 			while ( ( 0 != sibling ) && ( 0 == *previous ) )
817 			{
818 				sibling = sibling->PreviousSibling( value, false );
819 				*previous = dynamic_cast< T* >( sibling );
820 			}
821 		}
822 
823 		/**
824 		Navigate to a sibling element.
825 		Wrapper around TiXmlNode::NextSibling.
826 
827 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling element.
828 		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
829 		@throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true.
830 		*/
831 		Element* NextSiblingElement( bool throwIfNoSiblings = true ) const;
832 
833 		/**
834 		Navigate to a sibling element with the given @a value.
835 
836 		@overload
837 		@param value The value of the element to look for.
838 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements.
839 		@see NextSiblingElement( bool throwIfNoSiblings )
840 		*/
841 		Element* NextSiblingElement( const std::string& value, bool throwIfNoSiblings = true ) const;
842 
843 		/**
844 		@internal
845 		Navigate to a sibling element with the given @a value.
846 
847 		@overload
848 		@param value The value of the element to look for.
849 		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements.
850 
851 		@see NextSiblingElement( const std::string& value, bool throwIfNoSiblings )
852 		*/
853 		Element* NextSiblingElement( const char* value, bool throwIfNoSiblings = true ) const;
854 
855 		/**
856 		The first child element of this node.
857 
858 		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
859 		@return Pointer to child, Null if no element children and 'throwIfNoChildren' is false.
860 		@throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChildElement returns Null.
861 
862 		@see TiXmlNode::FirstChildElement
863 		*/
864 		Element* FirstChildElement( bool throwIfNoChildren = true ) const;
865 
866 		/**
867 		@internal
868 		The first child element of this node with the matching @a value.
869 
870 		@overload
871 		@param value Value to match.
872 		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
873 
874 		@see FirstChildElement( bool throwIfNoChildren = true )
875 		*/
876 		Element* FirstChildElement( const char* value, bool throwIfNoChildren = true ) const;
877 
878 		/**
879 		The first child element of this node with the matching @a value.
880 
881 		@overload
882 		@param value Value to match.
883 		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
884 
885 		@see FirstChildElement( const char* value, bool throwIfNoChildren = true )
886 		*/
887 		Element* FirstChildElement( const std::string& value, bool throwIfNoChildren = true ) const;
888 
889 		/**
890 		Query the type (as TiXmlNode::NodeType ) of this node.
891 		*/
892 		int Type() const;
893 
894 		/**
895 		Return a pointer to the Document this node lives in.
896 
897 		@param throwIfNoDocument [DEF] If true, will throw an exception if this node is not linked under a Document.
898 		@return A pointer to the Document this node lives in, NULL if not linked under a Document, and 'throwIfNoDocument' is false.
899 		@throws Exception When this node is not linked under a Document and 'throwIfNoDocument' is true.
900 		*/
901 		Document* GetDocument( bool throwIfNoDocument = true ) const;
902 
903 		/**
904 		Check if this node has no children.
905 
906 		@return true if this node has no children.
907 		*/
908 		bool NoChildren() const;
909 
910 		#ifndef TICPP_NO_RTTI
911 		/**
912 		Pointer conversion ( NOT OBJECT CONVERSION ) - replaces TiXmlNode::ToElement, TiXmlNode::ToDocument, TiXmlNode::ToComment, etc.
913 
914 		@throws Exception When the target is not an object of class T
915 		@warning Some ancient compilers do not support explicit specification of member template arguments, which this depends on ( e.g. VC6 ).
916 		*/
917 		template < class T >
To()918 			T* To() const
919 		{
920 			T* pointer = dynamic_cast< T* >( this );
921 			if ( 0 == pointer )
922 			{
923 				std::string thisType = typeid( this ).name();
924 				std::string targetType = typeid( T ).name();
925 				std::string thatType = typeid( *this ).name();
926 				TICPPTHROW( "The " << thisType.substr( 6 ) << " could not be casted to a " << targetType.substr( 6 )
927 					<< " *, because the target object is not a " << targetType.substr( 6 ) << ". (It is a " << thatType.substr( 6 ) << ")" );
928 			}
929 			return pointer;
930 		}
931 		#endif
932 
933 		/**
934 		Pointer conversion - replaces TiXmlNode::ToDocument.
935 
936 		@throws Exception When this node is not a Document.
937 		*/
938 		Document* ToDocument() const;
939 
940 		/**
941 		Pointer conversion - replaces TiXmlNode::ToElement.
942 
943 		@throws Exception When this node is not a Element.
944 		*/
945 		Element* ToElement() const;
946 
947 		/**
948 		Pointer conversion - replaces TiXmlNode::ToComment.
949 
950 		@throws Exception When this node is not a Comment.
951 		*/
952 		Comment* ToComment() const;
953 
954 		/**
955 		Pointer conversion - replaces TiXmlNode::ToText.
956 
957 		@throws Exception When this node is not a Text.
958 		*/
959 		Text* ToText() const;
960 
961 		/**
962 		Pointer conversion - replaces TiXmlNode::ToDeclaration.
963 
964 		@throws Exception When this node is not a Declaration.
965 		*/
966 		Declaration* ToDeclaration() const;
967 
968 		/**
969 		Pointer conversion - replaces TiXmlNode::ToStylesheetReference.
970 
971 		@throws Exception When this node is not a StylesheetReference.
972 		*/
973 		StylesheetReference* ToStylesheetReference() const;
974 
975 		/**
976 		Create an exact duplicate of this node and return it.
977 
978 		@note Using auto_ptr to manage the memory declared on the heap by TiXmlNode::Clone.
979 		@code
980 		// Now using clone
981 		ticpp::Document doc( "C:\\Test.xml" );
982 		ticpp::Node* sectionToClone;
983 		sectionToClone = doc.FirstChild( "settings" );
984 		std::auto_ptr< ticpp::Node > clonedNode = sectionToClone->Clone();
985 		// Now you can use the clone.
986 		ticpp::Node* node2 = clonedNode->FirstChildElement()->FirstChild();
987 		...
988 		// After the variable clonedNode goes out of scope it will automatically be cleaned up.
989 		@endcode
990 		@return Pointer the duplicate node.
991 		*/
992 		std::auto_ptr< Node > Clone() const;
993 
994 		/**
995 		Accept a hierchical visit the nodes in the TinyXML DOM.
996 		@return The boolean returned by the visitor.
997 		*/
998 		bool Accept( TiXmlVisitor* visitor ) const;
999 
1000 		/**
1001  		Stream input operator.
1002  		*/
1003  		friend std::istream& operator >>( std::istream& in, Node& base )
1004  		{
1005  			in >> *base.GetTiXmlPointer();
1006  			return in;
1007  		}
1008 
1009  		/**
1010  		Stream output operator.
1011  		*/
1012  		friend std::ostream& operator <<( std::ostream& out, const Node& base )
1013  		{
1014  			out << *base.GetTiXmlPointer();
1015  			return out;
1016  		}
1017 
1018 	protected:
1019 		/**
1020 		@internal
1021 		Allows NodeImp to use Node*'s.
1022 		*/
1023 		virtual TiXmlNode* GetTiXmlPointer() const = 0;
1024 
GetBasePointer()1025 		TiXmlBase* GetBasePointer() const
1026 		{
1027 			return GetTiXmlPointer();
1028 		}
1029 
1030 		/**
1031 		@internal
1032 		Constructs the correct child of Node, based on the Type of the TiXmlNode*.
1033 		*/
1034 		Node* NodeFactory( TiXmlNode* tiXmlNode, bool throwIfNull = true, bool rememberSpawnedWrapper = true ) const;
1035 
1036 	};
1037 
1038 	/** Iterator for conveniently stepping through Nodes and Attributes.
1039 	TinyXML++ introduces iterators:
1040 	@code
1041 	ticpp::Iterator< ticpp::Node > child;
1042 	for ( child = child.begin( parent ); child != child.end(); child++ )
1043 	@endcode
1044 
1045 	Iterators have the added advantage of filtering by type:
1046 	@code
1047 	// Only iterates through Comment nodes
1048 	ticpp::Iterator< ticpp::Comment > child;
1049 	for ( child = child.begin( parent ); child != child.end(); child++ )
1050 	@endcode
1051 
1052 	@code
1053 	// Only iterates through Element nodes with value "ElementValue"
1054 	ticpp::Iterator< ticpp::Element > child( "ElementValue" );
1055 	for ( child = child.begin( parent ); child != child.end(); child++ )
1056 	@endcode
1057 
1058 	Finally, Iterators also work with Attributes
1059 	@code
1060 	ticpp::Iterator< ticpp::Attribute > attribute;
1061 	for ( attribute = attribute.begin( element ); attribute != attribute.end(); attribute++ )
1062 	@endcode
1063 	*/
1064 	template < class T = Node >
1065 		class Iterator
1066 	{
1067 	private:
1068 		T* m_p;					/**< Internal Pointer */
1069 		std::string m_value;	/**< Value for NextSibling  calls */
1070 
1071 	public:
1072 
1073 		/**
1074 		For for loop comparisons.
1075 		@param parent The parent of the nodes to iterate.
1076 		@return The first child of type T.
1077 		@code
1078 		ticpp::Iterator< ticpp::Node > child;
1079 		for ( child = child.begin( parent ); child != child.end(); child++ )
1080 		@endcode
1081 		*/
begin(const Node * parent)1082 		T* begin( const Node* parent ) const
1083 		{
1084 			T* pointer;
1085 			parent->IterateFirst( m_value, &pointer );
1086 			return pointer;
1087 		}
1088 
1089 		/**
1090 		For for loop comparisons.
1091 		@return NULL
1092 		@code
1093 		ticpp::Iterator< ticpp::Node > child;
1094 		for ( child = child.begin( parent ); child != child.end(); child++ )
1095 		@endcode
1096 		*/
end()1097 		T* end() const
1098 		{
1099 			return 0;
1100 		}
1101 
1102 		/** Constructor.
1103 		@param value If not empty, this iterator will only visit nodes with matching value.
1104 		@code
1105 		// Only iterates through Element nodes with value "ElementValue"
1106 		ticpp::Iterator< ticpp::Element > child( "ElementValue" );
1107 		for ( child = child.begin( parent ); child != child.end(); child++ )
1108 		@endcode
1109 		*/
1110 		Iterator( const std::string& value = "" )
1111 			: m_p( 0 ), m_value( value )
1112 		{
1113 		}
1114 
1115 		/// Constructor
1116 		Iterator( T* node, const std::string& value = "" )
m_p(node)1117 			: m_p( node ), m_value( value )
1118 		{
1119 		}
1120 
1121 		/// Constructor
Iterator(const Iterator & it)1122 		Iterator( const Iterator& it )
1123 			: m_p( it.m_p ), m_value( it.m_value )
1124 		{
1125 		}
1126 
1127 		/**
1128 		Gets internal pointer.
1129 		@return The internal pointer.
1130 		*/
Get()1131 		T* Get() const
1132 		{
1133 			return m_p;
1134 		}
1135 
1136 		/** Sets internal pointer */
1137 		Iterator& operator=( const Iterator& it )
1138 		{
1139 			m_p = it.m_p;
1140 			m_value = it.m_value;
1141 			return *this;
1142 		}
1143 
1144 		/** Sets internal pointer */
1145 		Iterator& operator=( T* p )
1146 		{
1147 			m_p = p;
1148 			return *this;
1149 		}
1150 
1151 		/** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */
1152 		Iterator& operator++()
1153 		{
1154 			m_p->IterateNext( m_value, &m_p );
1155 			return *this;
1156 		}
1157 
1158 		/** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */
1159 		Iterator operator++(int)
1160 		{
1161 			Iterator tmp(*this);
1162 			++(*this);
1163 			return tmp;
1164 		}
1165 
1166 		/** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */
1167 		Iterator& operator--()
1168 		{
1169 			m_p->IteratePrevious( m_value, &m_p );
1170 			return *this;
1171 		}
1172 
1173 		/** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */
1174 		Iterator operator--(int)
1175 		{
1176 			Iterator tmp(*this);
1177 			--(*this);
1178 			return tmp;
1179 		}
1180 
1181 		/** Compares internal pointer */
1182 		bool operator!=( const T* p ) const
1183 		{
1184 			if ( m_p == p )
1185 			{
1186 				return false;
1187 			}
1188 			if ( 0 == m_p || 0 == p )
1189 			{
1190 				return true;
1191 			}
1192 			return *m_p != *p;
1193 		}
1194 
1195 		/** Compares internal pointer */
1196 		bool operator!=( const Iterator& it ) const
1197 		{
1198 			return operator!=( it.m_p );
1199 		}
1200 
1201 		/** Compares internal pointer* */
1202 		bool operator==( T* p ) const
1203 		{
1204 			if ( m_p == p )
1205 			{
1206 				return true;
1207 			}
1208 			if ( 0 == m_p || 0 == p )
1209 			{
1210 				return false;
1211 			}
1212 			return *m_p == *p;
1213 		}
1214 
1215 		/** Compares internal pointer */
1216 		bool operator==( const Iterator& it ) const
1217 		{
1218 			return operator==( it.m_p );
1219 		}
1220 
1221 		/** So Iterator behaves like a STL iterator */
1222 		T* operator->() const
1223 		{
1224 			return m_p;
1225 		}
1226 
1227 		/** So Iterator behaves like a STL iterator */
1228 		T& operator*() const
1229 		{
1230 			return *m_p;
1231 		}
1232 	};
1233 
1234 	/** Implementation of Node wrapper */
1235 	template < class T >
1236 		class NodeImp : public Node
1237 	{
1238 	protected:
1239 
1240 		T* m_tiXmlPointer;		/**< Internal pointer to the TiXml Class which is being wrapped */
1241 
1242 		/**
1243 		@internal
1244 		Gets the internal TinyXML pointer.
1245 
1246 		@returns The internal TiXmlNode*.
1247 		*/
GetTiXmlPointer()1248 		TiXmlNode* GetTiXmlPointer() const
1249 		{
1250 			ValidatePointer();
1251 			return m_tiXmlPointer;
1252 		}
1253 
1254 		/**
1255 		@internal
1256 		Sets the internal pointer.
1257 		Saves a copy of the pointer to the RC object.
1258 
1259 		@param newPointer TiXmlNode* to set.
1260 		*/
SetTiXmlPointer(T * newPointer)1261 		void SetTiXmlPointer( T* newPointer )
1262 		{
1263 			m_tiXmlPointer = newPointer;
1264 			SetImpRC( newPointer );
1265 		}
1266 
1267 		/**
1268 		@internal
1269 		Constructor used by child classes.
1270 		*/
NodeImp(T * tiXmlPointer)1271 		NodeImp( T* tiXmlPointer )
1272 		{
1273 			// Check for NULL pointers
1274 			if ( 0 == tiXmlPointer )
1275 			{
1276 				#ifdef TICPP_NO_RTTI
1277 					TICPPTHROW( "Can not create TinyXML objext" );
1278 				#else
1279 					TICPPTHROW( "Can not create a " << typeid( T ).name() );
1280 				#endif
1281 			}
1282 			SetTiXmlPointer( tiXmlPointer );
1283 			m_impRC->IncRef();
1284 		}
1285 
1286 		/**
1287 		@internal
1288 		Updates the reference count for the old and new pointers.
1289 		In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in.
1290 		*/
1291 		virtual void operator=( const NodeImp<T>& copy )
1292 		{
1293 			// Dropping the reference to the old object
1294 			this->m_impRC->DecRef();
1295 
1296 			// Pointing to the new Object
1297 			SetTiXmlPointer( copy.m_tiXmlPointer );
1298 
1299 			// The internal tixml pointer changed in the above line
1300 			this->m_impRC->IncRef();
1301 		}
1302 
1303 		/**
1304 		@internal
1305 		Updates the reference count for the old and new pointers.
1306 		In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in
1307 		*/
NodeImp(const NodeImp<T> & copy)1308 		NodeImp( const NodeImp<T>& copy ) : Node( copy )
1309 		{
1310 			// Pointing to the new Object
1311 			SetTiXmlPointer( copy.m_tiXmlPointer );
1312 
1313 			// The internal tixml pointer changed in the above line
1314 			this->m_impRC->IncRef();
1315 		}
1316 
1317 	public:
1318 
1319 		/*
1320 		Deletes the spawned wrapper objects.
1321 		Decrements reference count.
1322 		*/
~NodeImp()1323 		virtual ~NodeImp()
1324 		{
1325 			m_impRC->DecRef();
1326 		}
1327 	};
1328 
1329 	/** Wrapper around TiXmlComment */
1330 	class TICPP_API Comment : public NodeImp< TiXmlComment >
1331 	{
1332 	public:
1333 
1334 		/**
1335 		Constructor.
1336 		*/
1337 		Comment();
1338 
1339 		/**
1340 		Constructor.
1341 		*/
1342 		Comment( TiXmlComment* comment );
1343 
1344 		/**
1345 		Constructor.
1346 		*/
1347 		Comment( const std::string& comment );
1348 	};
1349 
1350 	/** Wrapper around TiXmlText */
1351 	class TICPP_API Text : public NodeImp< TiXmlText >
1352 	{
1353 	public:
1354 
1355 		/**
1356 		Constructor.
1357 		*/
1358 		Text();
1359 
1360 		/**
1361 		Constructor.
1362 		@overload
1363 		*/
1364 		Text( TiXmlText* text );
1365 
1366 		/**
1367 		Constructor.
1368 		@overload
1369 		*/
1370 		Text( const std::string& value );
1371 
1372 		/**
1373 		Streams value into a string and creates a Text with it.
1374 		Uses ToString to covert the parameter to a string.
1375 
1376 		@param value The value of the Text node.
1377 		@throws Exception
1378 
1379 		@see TiXmlText
1380         */
1381 		template < class T >
Text(const T & value)1382 			Text( const T& value )
1383 				: NodeImp< TiXmlText >( new TiXmlText( ToString( value ) ) )
1384 		{
1385 			m_impRC->InitRef();
1386 		}
1387 	};
1388 
1389 	/** Wrapper around TiXmlDocument */
1390 	class TICPP_API Document : public NodeImp< TiXmlDocument >
1391 	{
1392 	public:
1393 		/**
1394 		Default	Constructor.
1395 		Create an empty document, that has no name.
1396 		*/
1397 		Document();
1398 
1399 		/**
1400 		Constructor.
1401 		*/
1402 		Document( TiXmlDocument* document );
1403 
1404 		/**
1405 		Constructor.
1406 		*/
1407 		Document( const char* documentName );
1408 
1409 		/**
1410 		 * Constructor.
1411 		 * Create a document with a name. The name of the document is also the filename of the xml.
1412 		 * @param documentName Name to set in the Document.
1413 		 * @note LoadFile() needs to be called to actually load the data from the file specified by documentName
1414 		 * 		 SaveFile() needs to be called to save data to file specified by documentName.
1415 		 */
1416 		Document( const std::string& documentName );
1417 
1418 		/**
1419 		Load a file using the current document value. Throws if load is unsuccessful.
1420 
1421 		@param encoding Sets the documents encoding.
1422 		@see TiXmlEncoding
1423 		@throws Exception
1424 		*/
1425 		void LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1426 
1427 		/**
1428 		Save a file using the current document value. Throws if it can't save the file.
1429 
1430 		@throws Exception
1431 		*/
1432 		void SaveFile() const;
1433 
1434 		/**
1435 		Load a file using the given filename. Throws if load is unsuccessful.
1436 
1437 		@param filename File to load.
1438 		@param encoding Sets the documents encoding.
1439 		@see TiXmlEncoding
1440 		@throws Exception
1441 		*/
1442 		void LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1443 
1444 		/**
1445 		@copydoc Document::LoadFile( const std::string&, TiXmlEncoding )
1446 		*/
1447 		void LoadFile( const char* filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1448 
1449 		/**
1450 		Save a file using the given filename. Throws if it can't save the file.
1451 
1452 		@param filename File to save.
1453 		@throws Exception
1454 		*/
1455 		void SaveFile( const std::string& filename ) const;
1456 
1457 		/**
1458 		Parse the given xml data.
1459 
1460 		@param xml Xml to parse.
1461 		@param throwIfParseError [DEF] If true, throws when there is a parse error.
1462 		@param encoding Sets the documents encoding.
1463 		@throws Exception
1464 		*/
1465 		void Parse( const std::string& xml, bool throwIfParseError = true, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1466 	};
1467 
1468 	/** Wrapper around TiXmlElement */
1469 	class TICPP_API Element : public NodeImp< TiXmlElement >
1470 	{
1471 	public:
1472 		/**
1473 		Default Constructor.
1474 		*/
1475 		Element();
1476 
1477 		/**
1478 		Default	Constructor. Initializes all the variables.
1479 		@param value The value of the element.
1480 		*/
1481 		Element( const std::string& value );
1482 
1483 		/**
1484 		Default	Constructor. Initializes all the variables.
1485 		@param value The value of the element.
1486 		*/
1487 		Element( const char* value );
1488 
1489 		/**
1490 		Constructor.
1491 		*/
1492 		Element( TiXmlElement* element );
1493 
1494 		/**
1495 		Constructor that allows you to set the element text
1496 		@param value The value of the element.
1497 		@param text The text to set.
1498 		*/
1499 		template < class T >
Element(const std::string & value,const T & text)1500 			Element( const std::string& value, const T& text )
1501 			: NodeImp< TiXmlElement >( new TiXmlElement( value ) )
1502 		{
1503 			m_impRC->InitRef();
1504 			SetText( text );
1505 		}
1506 
1507 		/**
1508 		Access the first attribute in this element.
1509 
1510 		@param throwIfNoAttributes [DEF] If true, throws when there are no attributes
1511 		@return The first attribute, NULL if there are none and @a throwIfNoAttributes is true
1512 		*/
1513 		Attribute* FirstAttribute( bool throwIfNoAttributes = true ) const;
1514 
1515 		/**
1516 		Access the last attribute in this element.
1517 
1518 		@param throwIfNoAttributes [DEF] If true, throws when there are no attributes
1519 		@return The last attribute, NULL if there are none and @a throwIfNoAttributes is true
1520 		*/
1521 		Attribute* LastAttribute( bool throwIfNoAttributes = true ) const;
1522 
1523 		/**
1524 		@internal
1525 		Just for Iterator<>
1526 
1527 		@param value The value of nodes to iterate through
1528 		@param next [OUT] The pointer to the first valid node
1529 		*/
IterateFirst(const std::string &,Attribute ** first)1530 		void IterateFirst( const std::string&, Attribute** first ) const
1531 		{
1532 			*first = 0;
1533 			for( Attribute* child = FirstAttribute( false ); child; child = child->Next( false ) )
1534 			{
1535 				*first = dynamic_cast< Attribute* >( child );
1536 				if ( 0 != *first )
1537 				{
1538 					return;
1539 				}
1540 			}
1541 		}
1542 
1543 		/**
1544 		Sets an attribute of name to a given value.
1545 		The attribute will be created if it does not exist, or changed if it does.
1546 		Uses ToString to convert the @a value to a string, so there is no need to use any other SetAttribute methods.
1547 
1548 		@see GetAttribute
1549 		*/
1550 		template < class T >
SetAttribute(const std::string & name,const T & value)1551 			void SetAttribute ( const std::string& name, const T& value )
1552 		{
1553 			ValidatePointer();
1554 			m_tiXmlPointer->SetAttribute( name, ToString( value ) );
1555 		}
1556 
1557 		/**
1558 		Gets the text of an Element.
1559 
1560 		@param throwIfNotFound	[DEF]	If true, will throw an exception if there is no text in this element
1561 		@note This only works if the Text is the FirstChild node
1562 		@throws Exception When there is no text and throwIfNotFound is true
1563 
1564 		@see GetText( T* value, bool throwIfNotFound = false )
1565 		@see GetTextOrDefault
1566 		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
1567 		@see TiXmlElement::GetText
1568 		*/
1569 		std::string GetText( bool throwIfNotFound = true ) const
1570 		{
1571 			// Get the element's text value as a std::string
1572 			std::string temp;
1573 			if ( !GetTextImp( &temp ) )
1574 			{
1575 				if ( throwIfNotFound )
1576 				{
1577 					TICPPTHROW( "Text does not exists in the current element" );
1578 				}
1579 			}
1580 
1581 			return temp;
1582 		}
1583 
1584 		/**
1585 		Gets the text of an Element, if it doesn't exist it will return the defaultValue.
1586 
1587 		@param defaultValue			What to put in 'value' if there is no text in this element
1588 		@note This only works if the Text is the FirstChild node
1589 
1590 		@see GetText
1591 		@see GetText( T* value, bool throwIfNotFound = false )
1592 		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
1593 		@see TiXmlElement::GetText
1594 		*/
GetTextOrDefault(const std::string & defaultValue)1595 		std::string GetTextOrDefault( const std::string& defaultValue ) const
1596 		{
1597 			// Get the element's text value as a std::string
1598 			std::string temp;
1599 			if ( !GetTextImp( &temp ) )
1600 			{
1601 				return defaultValue;
1602 			}
1603 
1604 			return temp;
1605 		}
1606 
1607 		/**
1608 		Gets the text value of an Element, if it doesn't exist it will return the defaultValue.
1609 		Uses FromString to convert the string to the type of choice
1610 
1611 		@param value		[OUT]	The container for the returned value
1612 		@param defaultValue			What to put in 'value' if there is no text in this element
1613 		@note This is different than GetText() in that it will covert the text to what ever type you want.
1614 		@note This only works if the Text is the FirstChild node
1615 
1616 		@see GetText
1617 		@see GetText( T* value, bool throwIfNotFound = false )
1618 		@see GetTextOrDefault( const std::string& defaultValue )
1619 		@see TiXmlElement::GetText
1620 		*/
1621 		template < class T, class DefaultT >
GetTextOrDefault(T * value,const DefaultT & defaultValue)1622 			void GetTextOrDefault( T* value, const DefaultT& defaultValue ) const
1623 		{
1624 			// Get the element's text value as a std::string
1625 			std::string temp;
1626 			if ( !GetTextImp( &temp ) )
1627 			{
1628 				// The text value does not exist - set value to the default
1629 				*value = defaultValue;
1630 				return;
1631 			}
1632 
1633 			// Stream the value from the string to T
1634 			FromString( temp, value );
1635 		}
1636 
1637 		/**
1638 		Gets the text of an Element.
1639 		Uses FromString to convert the string to the type of choice.
1640 
1641 		@param value			[OUT]	The container for the returned value
1642 		@param throwIfNotFound	[DEF]	If true, will throw an exception if there is no text in this element
1643 		@note This is different than GetText() in that it will covert the text to what ever type you want
1644 		@note This only works if the Text is the FirstChild node
1645 		@throws Exception When there is no text and throwIfNotFound is true
1646 
1647 		@see GetText
1648 		@see GetTextOrDefault
1649 		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
1650 		@see TiXmlElement::GetText
1651 		*/
1652 		template< class T >
1653 			void GetText( T* value, bool throwIfNotFound = true ) const
1654 		{
1655 			// Get the element's text value as a std::string
1656 			std::string temp;
1657 			if ( !GetTextImp( &temp ) )
1658 			{
1659 				if ( throwIfNotFound )
1660 				{
1661 					TICPPTHROW( "Text does not exists in the current element" );
1662 				}
1663 				else
1664 				{
1665 					return;
1666 				}
1667 			}
1668 
1669 			// Stream the value from the string to T
1670 			FromString( temp, value );
1671 		}
1672 
1673 		/**
1674 		Convenience function to set the text of an element.
1675 		Creates a Text node and inserts it as the first child.
1676 		Uses ToString to convert the parameter to a string.
1677 
1678 		@param value The text to set.
1679 		*/
1680 		template < class T >
SetText(const T & value)1681 			void SetText( const T& value )
1682 		{
1683 			ValidatePointer();
1684 			std::string temp = ToString( value );
1685 
1686 			if ( m_tiXmlPointer->NoChildren() )
1687 			{
1688 				m_tiXmlPointer->LinkEndChild( new TiXmlText( temp ) );
1689 			}
1690 			else
1691 			{
1692 				if ( 0 == m_tiXmlPointer->GetText() )
1693 				{
1694 					m_tiXmlPointer->InsertBeforeChild( m_tiXmlPointer->FirstChild(), TiXmlText( temp ) );
1695 				}
1696 				else
1697 				{
1698 					// There already is text, so change it
1699 					m_tiXmlPointer->FirstChild()->SetValue( temp );
1700 				}
1701 			}
1702 		}
1703 
1704 		/**
1705 		Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue.
1706 		Uses FromString to convert the string to the type of choice.
1707 
1708 		@param name			The name of the attribute you are querying.
1709 		@param value		[OUT] The container for the returned value.
1710 		@param defaultValue	What to put in @a value if there is no attribute in this element.
1711 		@throws Exception
1712 
1713 		@see GetAttribute
1714 		*/
1715 		template < class T, class DefaulT >
GetAttributeOrDefault(const std::string & name,T * value,const DefaulT & defaultValue)1716 			void GetAttributeOrDefault( const std::string& name, T* value, const DefaulT& defaultValue ) const
1717 		{
1718 			// Get the attribute's value as a std::string
1719 			std::string temp;
1720 			if ( !GetAttributeImp( name, &temp ) )
1721 			{
1722 				// The attribute does not exist - set value to the default
1723 				*value = defaultValue;
1724 				return;
1725 			}
1726 
1727 			// Stream the value from the string to T
1728 			FromString( temp, value );
1729 		}
1730 
1731 		/**
1732 		Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue.
1733 
1734 		@param name			The name of the attribute you are querying.
1735 		@param defaultValue	What to put in @a value if there is no attribute in this element.
1736 
1737 		@see GetAttribute
1738 		*/
1739 		std::string GetAttributeOrDefault( const std::string& name, const std::string& defaultValue ) const;
1740 
1741 		/**
1742 		Returns an attribute of @a name from an element.
1743 		Uses FromString to convert the string to the type of choice.
1744 
1745 		@param name				The name of the attribute you are querying.
1746 		@param throwIfNotFound	[DEF]	If true, will throw an exception if the attribute doesn't exist
1747 		@throws Exception When the attribute doesn't exist and throwIfNotFound is true
1748 		@see GetAttributeOrDefault
1749 		*/
1750 		template < class T >
1751 			T GetAttribute( const std::string& name, bool throwIfNotFound = true ) const
1752 		{
1753 			// Get the attribute's value as a std::string
1754 			std::string temp;
1755 			T value;
1756 			if ( !GetAttributeImp( name, &temp ) )
1757 			{
1758 				if ( throwIfNotFound )
1759 				{
1760 					const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) );
1761 					TICPPTHROW( error );
1762 				}
1763 			}
1764 			else
1765 			{
1766 				// Stream the value from the string to T
1767 				FromString( temp, &value );
1768 			}
1769 
1770 			return value;
1771 		}
1772 
1773 		/**
1774 		Gets an attribute of @a name from an element.
1775 		Uses FromString to convert the string to the type of choice.
1776 
1777 		@param name				The name of the attribute you are querying.
1778 		@param value			[OUT]	The container for the returned value
1779 		@param throwIfNotFound	[DEF]	If true, will throw an exception if the attribute doesn't exist
1780 		@throws Exception When the attribute doesn't exist and throwIfNotFound is true
1781 
1782 		@see GetAttributeOrDefault
1783 		*/
1784 		template< class T >
1785 			void GetAttribute( const std::string& name, T* value, bool throwIfNotFound = true ) const
1786 		{
1787 			// Get the attribute's value as a std::string
1788 			std::string temp;
1789 			if ( !GetAttributeImp( name, &temp ) )
1790 			{
1791 				if ( throwIfNotFound )
1792 				{
1793 					const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) );
1794 					TICPPTHROW( error );
1795 				}
1796 				else
1797 				{
1798 					return;
1799 				}
1800 			}
1801 
1802 			// Stream the value from the string to T
1803 			FromString( temp, value );
1804 		}
1805 
1806 		/**
1807 		Gets an attribute of @a name from an element.
1808 		Returns an empty string if the attribute does not exist.
1809 
1810 		@param name	The name of the attribute you are querying.
1811 		@return The value of the attribute, or an empty string if it does not exist.
1812 
1813 		@see GetAttributeOrDefault
1814 		*/
1815 		std::string GetAttribute( const std::string& name ) const;
1816 
1817 		/**
1818 		Returns true, if attribute exists
1819 
1820 		@param name The name of the attribute you are checking.
1821 		@return Existence of attribute
1822 		*/
1823 		bool HasAttribute( const std::string& name ) const;
1824 
1825 		/**
1826 		Removes attribute from element.
1827 
1828 		@param name The name of the attribute to remove.
1829 		*/
1830 		void RemoveAttribute( const std::string& name );
1831 
1832 	private:
1833 
1834 		/**
1835 		@internal
1836 		Implimentation of the GetAttribute and GetAttributeOrDefault template methods.
1837 		*/
1838 		bool GetAttributeImp( const std::string& name, std::string* value ) const;
1839 
1840 		/**
1841 		@internal
1842 		Implimentation of the GetText, GetTextOrDefault, GetTextValue, and GetTextValueOrDefault template methods.
1843 		*/
1844 		bool GetTextImp( std::string* value ) const;
1845 	};
1846 
1847 	/** Wrapper around TiXmlDeclaration */
1848 	class TICPP_API Declaration : public NodeImp< TiXmlDeclaration >
1849 	{
1850 	public:
1851 		/**
1852 		Default	Constructor. Construct an empty declaration.
1853 		*/
1854 		Declaration();
1855 
1856 		/**
1857 		Constructor.
1858 		*/
1859 		Declaration( TiXmlDeclaration* declaration );
1860 
1861 		/**
1862 		Constructor.
1863 		*/
1864 		Declaration( const std::string& version, const std::string& encoding, const std::string& standalone );
1865 
1866 		/**
1867 		Version. Will return an empty string if none was found.
1868 		*/
1869 		std::string Version() const;
1870 
1871 		/**
1872 		Encoding. Will return an empty string if none was found.
1873 		*/
1874 		std::string Encoding() const;
1875 
1876 		/**
1877 		StandAlone. Is this a standalone document?
1878 		*/
1879 		std::string Standalone() const;
1880 	};
1881 
1882 	/** Wrapper around TiXmlStylesheetReference */
1883 	class TICPP_API StylesheetReference : public NodeImp< TiXmlStylesheetReference >
1884 	{
1885 	public:
1886 		/**
1887 		Default	Constructor. Construct an empty declaration.
1888 		*/
1889 		StylesheetReference();
1890 
1891 		/**
1892 		Constructor.
1893 		*/
1894 		StylesheetReference( TiXmlStylesheetReference* stylesheetReference );
1895 
1896 		/**
1897 		Constructor.
1898 		*/
1899 		StylesheetReference( const std::string& type, const std::string& href );
1900 
1901 		/**
1902 		Type. Will return an empty string if none was found.
1903 		*/
1904 		std::string Type() const;
1905 
1906 		/**
1907 		Href. Will return an empty string if none was found.
1908 		*/
1909 		std::string Href() const;
1910 	};
1911 }
1912 
1913 #endif	// TICPP_INCLUDED
1914