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