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