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