tinyxml.h

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