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