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