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