1 /* 2 www.sourceforge.net/projects/tinyxml 3 Original code (2.0 and earlier )copyright (c) 2000-2002 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 #ifndef TINYXML_INCLUDED 26 #define TINYXML_INCLUDED 27 28 #include <cassert> 29 #include <cstring> 30 31 #ifdef TIXML_USE_STL 32 #include "filesystem/import.h" 33 #include <string> 34 #include <iostream> 35 #define TIXML_STRING std::string 36 #define TIXML_ISTREAM std::istream 37 #define TIXML_OSTREAM std::ostream 38 #else 39 #include "tinystr.h" 40 #define TIXML_STRING TiXmlString 41 #define TIXML_OSTREAM TiXmlOutStream 42 #endif 43 44 class TiXmlDocument; 45 class TiXmlElement; 46 class TiXmlComment; 47 class TiXmlUnknown; 48 class TiXmlAttribute; 49 class TiXmlText; 50 class TiXmlDeclaration; 51 class TiXmlParsingData; 52 53 const int TIXML_MAJOR_VERSION = 2; 54 const int TIXML_MINOR_VERSION = 3; 55 const int TIXML_PATCH_VERSION = 3; 56 57 /* Internal structure for tracking location of items 58 in the XML file. 59 */ 60 struct TiXmlCursor 61 { TiXmlCursorTiXmlCursor62 TiXmlCursor() { Clear(); } ClearTiXmlCursor63 void Clear() { row = col = -1; } 64 65 int row; // 0 based. 66 int col; // 0 based. 67 }; 68 69 70 // Only used by Attribute::Query functions 71 enum 72 { 73 TIXML_SUCCESS, 74 TIXML_NO_ATTRIBUTE, 75 TIXML_WRONG_TYPE 76 }; 77 78 79 // Used by the parsing routines. 80 enum TiXmlEncoding 81 { 82 TIXML_ENCODING_UNKNOWN, 83 TIXML_ENCODING_UTF8, 84 TIXML_ENCODING_LEGACY 85 }; 86 87 const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; 88 89 /** TiXmlBase is a base class for every class in TinyXml. 90 It does little except to establish that TinyXml classes 91 can be printed and provide some utility functions. 92 93 In XML, the document and elements can contain 94 other elements and other types of nodes. 95 96 @verbatim 97 A Document can contain: Element (container or leaf) 98 Comment (leaf) 99 Unknown (leaf) 100 Declaration( leaf ) 101 102 An Element can contain: Element (container or leaf) 103 Text (leaf) 104 Attributes (not on tree) 105 Comment (leaf) 106 Unknown (leaf) 107 108 A Decleration contains: Attributes (not on tree) 109 @endverbatim 110 */ 111 class TiXmlBase 112 { 113 friend class TiXmlNode; 114 friend class TiXmlElement; 115 friend class TiXmlDocument; 116 117 public: TiXmlBase()118 TiXmlBase() : userData(0) {} ~TiXmlBase()119 virtual ~TiXmlBase() {} 120 121 /** All TinyXml classes can print themselves to a stream. 122 This is a formatted print, and will insert tabs and newlines. 123 124 (For an unformatted stream, use the << operator.) 125 */ 126 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const = 0; 127 128 /** The world does not agree on whether white space should be kept or 129 not. In order to make everyone happy, these global, static functions 130 are provided to set whether or not TinyXml will condense all white space 131 into a single space or not. The default is to condense. Note changing this 132 values is not thread safe. 133 */ SetCondenseWhiteSpace(bool condense)134 static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } 135 136 /// Return the current white space setting. IsWhiteSpaceCondensed()137 static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } 138 139 /** Return the position, in the original source file, of this node or attribute. 140 The row and column are 1-based. (That is the first row and first column is 141 1,1). If the returns values are 0 or less, then the parser does not have 142 a row and column value. 143 144 Generally, the row and column value will be set when the TiXmlDocument::Load(), 145 TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set 146 when the DOM was created from operator>>. 147 148 The values reflect the initial load. Once the DOM is modified programmatically 149 (by adding or changing nodes and attributes) the new values will NOT update to 150 reflect changes in the document. 151 152 There is a minor performance cost to computing the row and column. Computation 153 can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. 154 155 @sa TiXmlDocument::SetTabSize() 156 */ Row()157 int Row() const { return location.row + 1; } Column()158 int Column() const { return location.col + 1; } ///< See Row() 159 SetUserData(void * user)160 void SetUserData( void* user ) { userData = user; } GetUserData()161 void* GetUserData() { return userData; } 162 163 // Table that returs, for a given lead byte, the total number of bytes 164 // in the UTF-8 sequence. 165 static const int utf8ByteTable[256]; 166 167 virtual const char* Parse( const char* p, 168 TiXmlParsingData* data, 169 TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; 170 171 enum 172 { 173 TIXML_NO_ERROR = 0, 174 TIXML_ERROR, 175 TIXML_ERROR_OPENING_FILE, 176 TIXML_ERROR_OUT_OF_MEMORY, 177 TIXML_ERROR_PARSING_ELEMENT, 178 TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, 179 TIXML_ERROR_READING_ELEMENT_VALUE, 180 TIXML_ERROR_READING_ATTRIBUTES, 181 TIXML_ERROR_PARSING_EMPTY, 182 TIXML_ERROR_READING_END_TAG, 183 TIXML_ERROR_PARSING_UNKNOWN, 184 TIXML_ERROR_PARSING_COMMENT, 185 TIXML_ERROR_PARSING_DECLARATION, 186 TIXML_ERROR_DOCUMENT_EMPTY, 187 TIXML_ERROR_EMBEDDED_NULL, 188 189 TIXML_ERROR_STRING_COUNT 190 }; 191 192 protected: 193 194 // See STL_STRING_BUG 195 // Utility class to overcome a bug. 196 class StringToBuffer 197 { 198 public: 199 StringToBuffer( const TIXML_STRING& str ); 200 ~StringToBuffer(); 201 char* buffer; 202 }; 203 204 static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); IsWhiteSpace(char c)205 inline static bool IsWhiteSpace( char c ) 206 { 207 return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); 208 } 209 210 virtual void StreamOut (TIXML_OSTREAM *) const = 0; 211 212 #ifdef TIXML_USE_STL 213 static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag ); 214 static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag ); 215 #endif 216 217 /* Reads an XML name into the string provided. Returns 218 a pointer just past the last character of the name, 219 or 0 if the function has an error. 220 */ 221 static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); 222 223 /* Reads text. Returns a pointer past the given end tag. 224 Wickedly complex options, but it keeps the (sensitive) code in one place. 225 */ 226 static const char* ReadText( const char* in, // where to start 227 TIXML_STRING* text, // the string read 228 bool ignoreWhiteSpace, // whether to keep the white space 229 const char* endTag, // what ends this text 230 bool ignoreCase, // whether to ignore case in the end tag 231 TiXmlEncoding encoding ); // the current encoding 232 233 // If an entity has been found, transform it into a character. 234 static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); 235 236 // Get a character, while interpreting entities. 237 // The length can be from 0 to 4 bytes. GetChar(const char * p,char * _value,int * length,TiXmlEncoding encoding)238 inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) 239 { 240 assert( p ); 241 if ( encoding == TIXML_ENCODING_UTF8 ) 242 { 243 *length = utf8ByteTable[ *((unsigned char*)p) ]; 244 assert( *length >= 0 && *length < 5 ); 245 } 246 else 247 { 248 *length = 1; 249 } 250 251 if ( *length == 1 ) 252 { 253 if ( *p == '&' ) 254 return GetEntity( p, _value, length, encoding ); 255 *_value = *p; 256 return p+1; 257 } 258 else if ( *length ) 259 { 260 strncpy( _value, p, *length ); 261 return p + (*length); 262 } 263 else 264 { 265 // Not valid text. 266 return 0; 267 } 268 } 269 270 // Puts a string to a stream, expanding entities as it goes. 271 // Note this should not contian the '<', '>', etc, or they will be transformed into entities! 272 static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out ); 273 274 static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); 275 276 // Return true if the next characters in the stream are any of the endTag sequences. 277 // Ignore case only works for english, and should only be relied on when comparing 278 // to Engilish words: StringEqual( p, "version", true ) is fine. 279 static bool StringEqual( const char* p, 280 const char* endTag, 281 bool ignoreCase, 282 TiXmlEncoding encoding ); 283 284 static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; 285 286 TiXmlCursor location; 287 288 /// Field containing a generic user pointer 289 void* userData; 290 291 // None of these methods are reliable for any language except English. 292 // Good for approximation, not great for accuracy. 293 static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); 294 static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); ToLower(int v,TiXmlEncoding encoding)295 inline static int ToLower( int v, TiXmlEncoding encoding ) 296 { 297 if ( encoding == TIXML_ENCODING_UTF8 ) 298 { 299 if ( v < 128 ) return tolower( v ); 300 return v; 301 } 302 else 303 { 304 return tolower( v ); 305 } 306 } 307 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); 308 309 private: 310 TiXmlBase( const TiXmlBase& ); // not implemented. 311 void operator=( const TiXmlBase& base ); // not allowed. 312 313 struct Entity 314 { 315 const char* str; 316 unsigned int strLength; 317 char chr; 318 }; 319 enum 320 { 321 NUM_ENTITY = 5, 322 MAX_ENTITY_LENGTH = 6 323 324 }; 325 static Entity entity[ NUM_ENTITY ]; 326 static bool condenseWhiteSpace; 327 }; 328 329 330 /** The parent class for everything in the Document Object Model. 331 (Except for attributes). 332 Nodes have siblings, a parent, and children. A node can be 333 in a document, or stand on its own. The type of a TiXmlNode 334 can be queried, and it can be cast to its more defined type. 335 */ 336 class TiXmlNode : public TiXmlBase 337 { 338 friend class TiXmlDocument; 339 friend class TiXmlElement; 340 341 public: 342 #ifdef TIXML_USE_STL 343 344 /** An input stream operator, for every class. Tolerant of newlines and 345 formatting, but doesn't expect them. 346 */ 347 friend std::istream& operator >> (std::istream& in, TiXmlNode& base); 348 349 /** An output stream operator, for every class. Note that this outputs 350 without any newlines or formatting, as opposed to Print(), which 351 includes tabs and new lines. 352 353 The operator<< and operator>> are not completely symmetric. Writing 354 a node to a stream is very well defined. You'll get a nice stream 355 of output, without any extra whitespace or newlines. 356 357 But reading is not as well defined. (As it always is.) If you create 358 a TiXmlElement (for example) and read that from an input stream, 359 the text needs to define an element or junk will result. This is 360 true of all input streams, but it's worth keeping in mind. 361 362 A TiXmlDocument will read nodes until it reads a root element, and 363 all the children of that root element. 364 */ 365 friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); 366 367 /// Appends the XML node or attribute to a std::string. 368 friend std::string& operator<< (std::string& out, const TiXmlNode& base ); 369 370 #else 371 // Used internally, not part of the public API. 372 friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base); 373 #endif 374 375 /** The types of XML nodes supported by TinyXml. (All the 376 unsupported types are picked up by UNKNOWN.) 377 */ 378 enum NodeType 379 { 380 DOCUMENT, 381 ELEMENT, 382 COMMENT, 383 UNKNOWN, 384 TEXT, 385 DECLARATION, 386 TYPECOUNT 387 }; 388 389 virtual ~TiXmlNode(); 390 391 /** The meaning of 'value' changes for the specific type of 392 TiXmlNode. 393 @verbatim 394 Document: filename of the xml file 395 Element: name of the element 396 Comment: the comment text 397 Unknown: the tag contents 398 Text: the text string 399 @endverbatim 400 401 The subclasses will wrap this function. 402 */ Value()403 const char * Value() const { return value.c_str (); } 404 405 /** Changes the value of the node. Defined as: 406 @verbatim 407 Document: filename of the xml file 408 Element: name of the element 409 Comment: the comment text 410 Unknown: the tag contents 411 Text: the text string 412 @endverbatim 413 */ SetValue(const char * _value)414 void SetValue(const char * _value) { value = _value;} 415 416 #ifdef TIXML_USE_STL 417 /// STL std::string form. SetValue(const std::string & _value)418 void SetValue( const std::string& _value ) 419 { 420 StringToBuffer buf( _value ); 421 SetValue( buf.buffer ? buf.buffer : "" ); 422 } 423 #endif 424 425 /// Delete all the children of this node. Does not affect 'this'. 426 void Clear(); 427 428 /// One step up the DOM. Parent()429 TiXmlNode* Parent() { return parent; } Parent()430 const TiXmlNode* Parent() const { return parent; } 431 FirstChild()432 const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. FirstChild()433 TiXmlNode* FirstChild() { return firstChild; } 434 const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. 435 TiXmlNode* FirstChild( const char * value ); ///< The first child of this node with the matching 'value'. Will be null if none found. 436 LastChild()437 const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. LastChild()438 TiXmlNode* LastChild() { return lastChild; } 439 const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. 440 TiXmlNode* LastChild( const char * value ); 441 442 #ifdef TIXML_USE_STL FirstChild(const std::string & _value)443 const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. FirstChild(const std::string & _value)444 TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. LastChild(const std::string & _value)445 const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. LastChild(const std::string & _value)446 TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. 447 #endif 448 449 /** An alternate way to walk the children of a node. 450 One way to iterate over nodes is: 451 @verbatim 452 for( child = parent->FirstChild(); child; child = child->NextSibling() ) 453 @endverbatim 454 455 IterateChildren does the same thing with the syntax: 456 @verbatim 457 child = 0; 458 while( child = parent->IterateChildren( child ) ) 459 @endverbatim 460 461 IterateChildren takes the previous child as input and finds 462 the next one. If the previous child is null, it returns the 463 first. IterateChildren will return null when done. 464 */ 465 const TiXmlNode* IterateChildren( TiXmlNode* previous ) const; 466 TiXmlNode* IterateChildren( TiXmlNode* previous ); 467 468 /// This flavor of IterateChildren searches for children with a particular 'value' 469 const TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const; 470 TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ); 471 472 #ifdef TIXML_USE_STL IterateChildren(const std::string & _value,TiXmlNode * previous)473 const TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. IterateChildren(const std::string & _value,TiXmlNode * previous)474 TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. 475 #endif 476 477 /** Add a new node related to this. Adds a child past the LastChild. 478 Returns a pointer to the new object or NULL if an error occured. 479 */ 480 TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); 481 482 483 /** Add a new node related to this. Adds a child past the LastChild. 484 485 NOTE: the node to be added is passed by pointer, and will be 486 henceforth owned (and deleted) by tinyXml. This method is efficient 487 and avoids an extra copy, but should be used with care as it 488 uses a different memory model than the other insert functions. 489 490 @sa InsertEndChild 491 */ 492 TiXmlNode* LinkEndChild( TiXmlNode* addThis ); 493 494 /** Add a new node related to this. Adds a child before the specified child. 495 Returns a pointer to the new object or NULL if an error occured. 496 */ 497 TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); 498 499 /** Add a new node related to this. Adds a child after the specified child. 500 Returns a pointer to the new object or NULL if an error occured. 501 */ 502 TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); 503 504 /** Replace a child of this node. 505 Returns a pointer to the new object or NULL if an error occured. 506 */ 507 TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); 508 509 /// Delete a child of this node. 510 bool RemoveChild( TiXmlNode* removeThis ); 511 512 /// Navigate to a sibling node. PreviousSibling()513 const TiXmlNode* PreviousSibling() const { return prev; } PreviousSibling()514 TiXmlNode* PreviousSibling() { return prev; } 515 516 /// Navigate to a sibling node. 517 const TiXmlNode* PreviousSibling( const char * ) const; 518 TiXmlNode* PreviousSibling( const char * ); 519 520 #ifdef TIXML_USE_STL PreviousSibling(const std::string & _value)521 const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. PreviousSibling(const std::string & _value)522 TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. NextSibling(const std::string & _value)523 const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. NextSibling(const std::string & _value)524 TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. 525 #endif 526 527 /// Navigate to a sibling node. NextSibling()528 const TiXmlNode* NextSibling() const { return next; } NextSibling()529 TiXmlNode* NextSibling() { return next; } 530 531 /// Navigate to a sibling node with the given 'value'. 532 const TiXmlNode* NextSibling( const char * ) const; 533 TiXmlNode* NextSibling( const char * ); 534 535 /** Convenience function to get through elements. 536 Calls NextSibling and ToElement. Will skip all non-Element 537 nodes. Returns 0 if there is not another element. 538 */ 539 const TiXmlElement* NextSiblingElement() const; 540 TiXmlElement* NextSiblingElement(); 541 542 /** Convenience function to get through elements. 543 Calls NextSibling and ToElement. Will skip all non-Element 544 nodes. Returns 0 if there is not another element. 545 */ 546 const TiXmlElement* NextSiblingElement( const char * ) const; 547 TiXmlElement* NextSiblingElement( const char * ); 548 549 #ifdef TIXML_USE_STL NextSiblingElement(const std::string & _value)550 const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. NextSiblingElement(const std::string & _value)551 TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. 552 #endif 553 554 /// Convenience function to get through elements. 555 const TiXmlElement* FirstChildElement() const; 556 TiXmlElement* FirstChildElement(); 557 558 /// Convenience function to get through elements. 559 const TiXmlElement* FirstChildElement( const char * value ) const; 560 TiXmlElement* FirstChildElement( const char * value ); 561 562 #ifdef TIXML_USE_STL FirstChildElement(const std::string & _value)563 const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. FirstChildElement(const std::string & _value)564 TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. 565 #endif 566 567 /** Query the type (as an enumerated value, above) of this node. 568 The possible types are: DOCUMENT, ELEMENT, COMMENT, 569 UNKNOWN, TEXT, and DECLARATION. 570 */ Type()571 virtual int Type() const { return type; } 572 573 /** Return a pointer to the Document this node lives in. 574 Returns null if not in a document. 575 */ 576 const TiXmlDocument* GetDocument() const; 577 TiXmlDocument* GetDocument(); 578 579 /// Returns true if this node has no children. NoChildren()580 bool NoChildren() const { return !firstChild; } 581 582 #if INEEDTHISAND 583 #define THISAND this && 584 #else 585 #define THISAND 586 #endif 587 ToDocument()588 const TiXmlDocument* ToDocument() const { return ( THISAND type == DOCUMENT ) ? (const TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToElement()589 const TiXmlElement* ToElement() const { return ( THISAND type == ELEMENT ) ? (const TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToComment()590 const TiXmlComment* ToComment() const { return ( THISAND type == COMMENT ) ? (const TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToUnknown()591 const TiXmlUnknown* ToUnknown() const { return ( THISAND type == UNKNOWN ) ? (const TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToText()592 const TiXmlText* ToText() const { return ( THISAND type == TEXT ) ? (const TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToDeclaration()593 const TiXmlDeclaration* ToDeclaration() const { return ( THISAND type == DECLARATION ) ? (const TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. 594 ToDocument()595 TiXmlDocument* ToDocument() { return ( THISAND type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToElement()596 TiXmlElement* ToElement() { return ( THISAND type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToComment()597 TiXmlComment* ToComment() { return ( THISAND type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToUnknown()598 TiXmlUnknown* ToUnknown() { return ( THISAND type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToText()599 TiXmlText* ToText() { return ( THISAND type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. ToDeclaration()600 TiXmlDeclaration* ToDeclaration() { return ( THISAND type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. 601 602 /** Create an exact duplicate of this node and return it. The memory must be deleted 603 by the caller. 604 */ 605 virtual TiXmlNode* Clone() const = 0; 606 607 protected: 608 TiXmlNode( NodeType _type ); 609 610 // Copy to the allocated object. Shared functionality between Clone, Copy constructor, 611 // and the assignment operator. 612 void CopyTo( TiXmlNode* target ) const; 613 614 #ifdef TIXML_USE_STL 615 // The real work of the input operator. 616 virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0; 617 #endif 618 619 // Figure out what is at *p, and parse it. Returns null if it is not an xml node. 620 TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); 621 622 // Internal Value function returning a TIXML_STRING SValue()623 const TIXML_STRING& SValue() const { return value ; } 624 625 TiXmlNode* parent; 626 NodeType type; 627 628 TiXmlNode* firstChild; 629 TiXmlNode* lastChild; 630 631 TIXML_STRING value; 632 633 TiXmlNode* prev; 634 TiXmlNode* next; 635 636 private: 637 TiXmlNode( const TiXmlNode& ); // not implemented. 638 void operator=( const TiXmlNode& base ); // not allowed. 639 }; 640 641 642 /** An attribute is a name-value pair. Elements have an arbitrary 643 number of attributes, each with a unique name. 644 645 @note The attributes are not TiXmlNodes, since they are not 646 part of the tinyXML document object model. There are other 647 suggested ways to look at this problem. 648 */ 649 class TiXmlAttribute : public TiXmlBase 650 { 651 friend class TiXmlAttributeSet; 652 653 public: 654 /// Construct an empty attribute. TiXmlAttribute()655 TiXmlAttribute() : TiXmlBase() 656 { 657 document = 0; 658 prev = next = 0; 659 } 660 661 #ifdef TIXML_USE_STL 662 /// std::string constructor. TiXmlAttribute(const std::string & _name,const std::string & _value)663 TiXmlAttribute( const std::string& _name, const std::string& _value ) 664 { 665 name = _name; 666 value = _value; 667 document = 0; 668 prev = next = 0; 669 } 670 #endif 671 672 /// Construct an attribute with a name and value. TiXmlAttribute(const char * _name,const char * _value)673 TiXmlAttribute( const char * _name, const char * _value ) 674 { 675 name = _name; 676 value = _value; 677 document = 0; 678 prev = next = 0; 679 } 680 Name()681 const char* Name() const { return name.c_str (); } ///< Return the name of this attribute. Value()682 const char* Value() const { return value.c_str (); } ///< Return the value of this attribute. 683 int IntValue() const; ///< Return the value of this attribute, converted to an integer. 684 double DoubleValue() const; ///< Return the value of this attribute, converted to a double. 685 686 /** QueryIntValue examines the value string. It is an alternative to the 687 IntValue() method with richer error checking. 688 If the value is an integer, it is stored in 'value' and 689 the call returns TIXML_SUCCESS. If it is not 690 an integer, it returns TIXML_WRONG_TYPE. 691 692 A specialized but useful call. Note that for success it returns 0, 693 which is the opposite of almost all other TinyXml calls. 694 */ 695 int QueryIntValue( int* value ) const; 696 /// QueryDoubleValue examines the value string. See QueryIntValue(). 697 int QueryDoubleValue( double* value ) const; 698 SetName(const char * _name)699 void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. SetValue(const char * _value)700 void SetValue( const char* _value ) { value = _value; } ///< Set the value. 701 702 void SetIntValue( int value ); ///< Set the value from an integer. 703 void SetDoubleValue( double value ); ///< Set the value from a double. 704 705 #ifdef TIXML_USE_STL 706 /// STL std::string form. SetName(const std::string & _name)707 void SetName( const std::string& _name ) 708 { 709 StringToBuffer buf( _name ); 710 SetName ( buf.buffer ? buf.buffer : "error" ); 711 } 712 /// STL std::string form. SetValue(const std::string & _value)713 void SetValue( const std::string& _value ) 714 { 715 StringToBuffer buf( _value ); 716 SetValue( buf.buffer ? buf.buffer : "error" ); 717 } 718 #endif 719 720 /// Get the next sibling attribute in the DOM. Returns null at end. 721 const TiXmlAttribute* Next() const; 722 TiXmlAttribute* Next(); 723 /// Get the previous sibling attribute in the DOM. Returns null at beginning. 724 const TiXmlAttribute* Previous() const; 725 TiXmlAttribute* Previous(); 726 727 bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } 728 bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } 729 bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } 730 731 /* Attribute parsing starts: first letter of the name 732 returns: the next char after the value end quote 733 */ 734 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 735 736 // Prints this Attribute to a stream. 737 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 738 739 virtual void StreamOut( TIXML_OSTREAM * out ) const override; 740 // [internal use] 741 // Set the document pointer so the attribute can report errors. SetDocument(TiXmlDocument * doc)742 void SetDocument( TiXmlDocument* doc ) { document = doc; } 743 744 private: 745 TiXmlAttribute( const TiXmlAttribute& ); // not implemented. 746 void operator=( const TiXmlAttribute& base ); // not allowed. 747 748 TiXmlDocument* document; // A pointer back to a document, for error reporting. 749 TIXML_STRING name; 750 TIXML_STRING value; 751 TiXmlAttribute* prev; 752 TiXmlAttribute* next; 753 }; 754 755 756 /* A class used to manage a group of attributes. 757 It is only used internally, both by the ELEMENT and the DECLARATION. 758 759 The set can be changed transparent to the Element and Declaration 760 classes that use it, but NOT transparent to the Attribute 761 which has to implement a next() and previous() method. Which makes 762 it a bit problematic and prevents the use of STL. 763 764 This version is implemented with circular lists because: 765 - I like circular lists 766 - it demonstrates some independence from the (typical) doubly linked list. 767 */ 768 class TiXmlAttributeSet 769 { 770 public: 771 TiXmlAttributeSet(); 772 ~TiXmlAttributeSet(); 773 774 void Add( TiXmlAttribute* attribute ); 775 void Remove( TiXmlAttribute* attribute ); 776 First()777 const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } First()778 TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } Last()779 const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } Last()780 TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } 781 782 const TiXmlAttribute* Find( const char * name ) const; 783 TiXmlAttribute* Find( const char * name ); 784 785 private: 786 //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), 787 //*ME: this class must be also use a hidden/disabled copy-constructor !!! 788 TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed 789 void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) 790 791 TiXmlAttribute sentinel; 792 }; 793 794 795 /** The element is a container class. It has a value, the element name, 796 and can contain other elements, text, comments, and unknowns. 797 Elements also contain an arbitrary number of attributes. 798 */ 799 class TiXmlElement : public TiXmlNode 800 { 801 public: 802 /// Construct an element. 803 TiXmlElement (const char * in_value); 804 805 #ifdef TIXML_USE_STL 806 /// std::string constructor. 807 TiXmlElement( const std::string& _value ); 808 #endif 809 810 TiXmlElement( const TiXmlElement& ); 811 812 void operator=( const TiXmlElement& base ); 813 814 virtual ~TiXmlElement(); 815 816 /** Given an attribute name, Attribute() returns the value 817 for the attribute of that name, or null if none exists. 818 */ 819 const char* Attribute( const char* name ) const; 820 821 /** Given an attribute name, Attribute() returns the value 822 for the attribute of that name, or null if none exists. 823 If the attribute exists and can be converted to an integer, 824 the integer value will be put in the return 'i', if 'i' 825 is non-null. 826 */ 827 const char* Attribute( const char* name, int* i ) const; 828 829 /** Given an attribute name, Attribute() returns the value 830 for the attribute of that name, or null if none exists. 831 If the attribute exists and can be converted to an double, 832 the double value will be put in the return 'd', if 'd' 833 is non-null. 834 */ 835 const char* Attribute( const char* name, double* d ) const; 836 837 /** QueryIntAttribute examines the attribute - it is an alternative to the 838 Attribute() method with richer error checking. 839 If the attribute is an integer, it is stored in 'value' and 840 the call returns TIXML_SUCCESS. If it is not 841 an integer, it returns TIXML_WRONG_TYPE. If the attribute 842 does not exist, then TIXML_NO_ATTRIBUTE is returned. 843 */ 844 int QueryIntAttribute( const char* name, int* value ) const; 845 /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). 846 int QueryDoubleAttribute( const char* name, double* value ) const; 847 /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). QueryDoubleAttribute(const char * name,float * value)848 int QueryDoubleAttribute( const char* name, float* value ) const { 849 double d; 850 int result = QueryDoubleAttribute( name, &d ); 851 *value = (float)d; 852 return result; 853 } 854 855 /** Sets an attribute of name to a given value. The attribute 856 will be created if it does not exist, or changed if it does. 857 */ 858 void SetAttribute( const char* name, const char * value ); 859 860 #ifdef TIXML_USE_STL Attribute(const std::string & name)861 const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); } Attribute(const std::string & name,int * i)862 const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); } Attribute(const std::string & name,double * d)863 const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); } QueryIntAttribute(const std::string & name,int * value)864 int QueryIntAttribute( const std::string& name, int* value ) const { return QueryIntAttribute( name.c_str(), value ); } QueryDoubleAttribute(const std::string & name,double * value)865 int QueryDoubleAttribute( const std::string& name, double* value ) const { return QueryDoubleAttribute( name.c_str(), value ); } 866 867 /// STL std::string form. SetAttribute(const std::string & name,const std::string & _value)868 void SetAttribute( const std::string& name, const std::string& _value ) 869 { 870 StringToBuffer n( name ); 871 StringToBuffer v( _value ); 872 if ( n.buffer && v.buffer ) 873 SetAttribute (n.buffer, v.buffer ); 874 } 875 ///< STL std::string form. SetAttribute(const std::string & name,int _value)876 void SetAttribute( const std::string& name, int _value ) 877 { 878 StringToBuffer n( name ); 879 if ( n.buffer ) 880 SetAttribute (n.buffer, _value); 881 } 882 #endif 883 884 /** Sets an attribute of name to a given value. The attribute 885 will be created if it does not exist, or changed if it does. 886 */ 887 void SetAttribute( const char * name, int value ); 888 889 /** Sets an attribute of name to a given value. The attribute 890 will be created if it does not exist, or changed if it does. 891 */ 892 void SetDoubleAttribute( const char * name, double value ); 893 894 /** Deletes an attribute with the given name. 895 */ 896 void RemoveAttribute( const char * name ); 897 #ifdef TIXML_USE_STL RemoveAttribute(const std::string & name)898 void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. 899 #endif 900 FirstAttribute()901 const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. FirstAttribute()902 TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } LastAttribute()903 const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. LastAttribute()904 TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } 905 906 /// Creates a new Element and returns it - the returned element is a copy. 907 virtual TiXmlNode* Clone() const override; 908 // Print the Element to a stream. 909 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 910 911 /* Attribtue parsing starts: next char past '<' 912 returns: next char past '>' 913 */ 914 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 915 916 protected: 917 918 void CopyTo( TiXmlElement* target ) const; 919 void ClearThis(); // like clear, but initializes 'this' object as well 920 921 // Used to be public [internal use] 922 #ifdef TIXML_USE_STL 923 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 924 #endif 925 virtual void StreamOut( TIXML_OSTREAM * out ) const override; 926 927 /* [internal use] 928 Reads the "value" of the element -- another element, or text. 929 This should terminate with the current end tag. 930 */ 931 const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); 932 933 private: 934 935 TiXmlAttributeSet attributeSet; 936 }; 937 938 939 /** An XML comment. 940 */ 941 class TiXmlComment : public TiXmlNode 942 { 943 public: 944 /// Constructs an empty comment. TiXmlComment()945 TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} 946 TiXmlComment( const TiXmlComment& ); 947 void operator=( const TiXmlComment& base ); 948 ~TiXmlComment()949 virtual ~TiXmlComment() {} 950 951 /// Returns a copy of this Comment. 952 virtual TiXmlNode* Clone() const override; 953 /// Write this Comment to a stream. 954 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 955 956 /* Attribtue parsing starts: at the ! of the !-- 957 returns: next char past '>' 958 */ 959 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 960 961 protected: 962 void CopyTo( TiXmlComment* target ) const; 963 964 // used to be public 965 #ifdef TIXML_USE_STL 966 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 967 #endif 968 virtual void StreamOut( TIXML_OSTREAM * out ) const override; 969 970 private: 971 972 }; 973 974 975 /** XML text. Contained in an element. 976 */ 977 class TiXmlText : public TiXmlNode 978 { 979 friend class TiXmlElement; 980 public: 981 /// Constructor. TiXmlText(const char * initValue)982 TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT) 983 { 984 SetValue( initValue ); 985 } ~TiXmlText()986 virtual ~TiXmlText() {} 987 988 #ifdef TIXML_USE_STL 989 /// Constructor. TiXmlText(const std::string & initValue)990 TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) 991 { 992 SetValue( initValue ); 993 } 994 #endif 995 TiXmlText(const TiXmlText & copy)996 TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } 997 void operator=( const TiXmlText& base ) { base.CopyTo( this ); } 998 999 /// Write this text object to a stream. 1000 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 1001 1002 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 1003 1004 protected : 1005 /// [internal use] Creates a new Element and returns it. 1006 virtual TiXmlNode* Clone() const override; 1007 void CopyTo( TiXmlText* target ) const; 1008 1009 virtual void StreamOut ( TIXML_OSTREAM * out ) const override; 1010 bool Blank() const; // returns true if all white space and new lines 1011 // [internal use] 1012 #ifdef TIXML_USE_STL 1013 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 1014 #endif 1015 1016 private: 1017 }; 1018 1019 1020 /** In correct XML the declaration is the first entry in the file. 1021 @verbatim 1022 <?xml version="1.0" standalone="yes"?> 1023 @endverbatim 1024 1025 TinyXml will happily read or write files without a declaration, 1026 however. There are 3 possible attributes to the declaration: 1027 version, encoding, and standalone. 1028 1029 Note: In this version of the code, the attributes are 1030 handled as special cases, not generic attributes, simply 1031 because there can only be at most 3 and they are always the same. 1032 */ 1033 class TiXmlDeclaration : public TiXmlNode 1034 { 1035 public: 1036 /// Construct an empty declaration. TiXmlDeclaration()1037 TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} 1038 1039 #ifdef TIXML_USE_STL 1040 /// Constructor. 1041 TiXmlDeclaration( const std::string& _version, 1042 const std::string& _encoding, 1043 const std::string& _standalone ); 1044 #endif 1045 1046 /// Construct. 1047 TiXmlDeclaration( const char* _version, 1048 const char* _encoding, 1049 const char* _standalone ); 1050 1051 TiXmlDeclaration( const TiXmlDeclaration& copy ); 1052 void operator=( const TiXmlDeclaration& copy ); 1053 ~TiXmlDeclaration()1054 virtual ~TiXmlDeclaration() {} 1055 1056 /// Version. Will return an empty string if none was found. Version()1057 const char *Version() const { return version.c_str (); } 1058 /// Encoding. Will return an empty string if none was found. Encoding()1059 const char *Encoding() const { return encoding.c_str (); } 1060 /// Is this a standalone document? Standalone()1061 const char *Standalone() const { return standalone.c_str (); } 1062 1063 /// Creates a copy of this Declaration and returns it. 1064 virtual TiXmlNode* Clone() const override; 1065 /// Print this declaration to a stream. 1066 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 1067 1068 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 1069 1070 protected: 1071 void CopyTo( TiXmlDeclaration* target ) const; 1072 // used to be public 1073 #ifdef TIXML_USE_STL 1074 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 1075 #endif 1076 virtual void StreamOut ( TIXML_OSTREAM * out) const override; 1077 1078 private: 1079 1080 TIXML_STRING version; 1081 TIXML_STRING encoding; 1082 TIXML_STRING standalone; 1083 }; 1084 1085 1086 /** Any tag that tinyXml doesn't recognize is saved as an 1087 unknown. It is a tag of text, but should not be modified. 1088 It will be written back to the XML, unchanged, when the file 1089 is saved. 1090 1091 DTD tags get thrown into TiXmlUnknowns. 1092 */ 1093 class TiXmlUnknown : public TiXmlNode 1094 { 1095 public: TiXmlUnknown()1096 TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} ~TiXmlUnknown()1097 virtual ~TiXmlUnknown() {} 1098 TiXmlUnknown(const TiXmlUnknown & copy)1099 TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } 1100 void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } 1101 1102 /// Creates a copy of this Unknown and returns it. 1103 virtual TiXmlNode* Clone() const override; 1104 /// Print this Unknown to a stream. 1105 virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; 1106 1107 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; 1108 1109 protected: 1110 void CopyTo( TiXmlUnknown* target ) const; 1111 1112 #ifdef TIXML_USE_STL 1113 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 1114 #endif 1115 virtual void StreamOut ( TIXML_OSTREAM * out ) const override; 1116 1117 private: 1118 1119 }; 1120 1121 1122 /** Always the top level node. A document binds together all the 1123 XML pieces. It can be saved, loaded, and printed to the screen. 1124 The 'value' of a document node is the xml file name. 1125 */ 1126 class TiXmlDocument : public TiXmlNode 1127 { 1128 public: 1129 /// Create an empty document, that has no name. 1130 TiXmlDocument(); 1131 /// Create a document with a name. The name of the document is also the filename of the xml. 1132 TiXmlDocument( const char * documentName ); 1133 1134 #ifdef TIXML_USE_STL 1135 /// Constructor. 1136 TiXmlDocument( const std::string& documentName ); 1137 #endif 1138 1139 TiXmlDocument( const TiXmlDocument& copy ); 1140 void operator=( const TiXmlDocument& copy ); 1141 ~TiXmlDocument()1142 virtual ~TiXmlDocument() {} 1143 1144 /** Load a file using the current document value. 1145 Returns true if successful. Will delete any existing 1146 document data before loading. 1147 */ 1148 bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1149 /// Save a file using the current document value. Returns true if successful. 1150 bool SaveFile() const; 1151 #ifndef TIXML_USE_STL 1152 /// Load a file using the given filename. Returns true if successful. 1153 bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1154 /// Save a file using the given filename. Returns true if successful. 1155 bool SaveFile( const char * filename ) const; 1156 #else // !TIXML_USE_STL 1157 bool LoadFile( const fs::path& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); 1158 bool SaveFile( const fs::path& filename ) const; 1159 #endif // TIXML_USE_STL 1160 1161 /** Parse the given null terminated block of xml data. Passing in an encoding to this 1162 method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml 1163 to use that encoding, regardless of what TinyXml might otherwise try to detect. 1164 */ 1165 virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) override; 1166 1167 /** Get the root element -- the only top level element -- of the document. 1168 In well formed XML, there should only be one. TinyXml is tolerant of 1169 multiple elements at the document level. 1170 */ RootElement()1171 const TiXmlElement* RootElement() const { return FirstChildElement(); } RootElement()1172 TiXmlElement* RootElement() { return FirstChildElement(); } 1173 1174 /** If an error occurs, Error will be set to true. Also, 1175 - The ErrorId() will contain the integer identifier of the error (not generally useful) 1176 - The ErrorDesc() method will return the name of the error. (very useful) 1177 - The ErrorRow() and ErrorCol() will return the location of the error (if known) 1178 */ Error()1179 bool Error() const { return error; } 1180 1181 /// Contains a textual (english) description of the error if one occurs. ErrorDesc()1182 const char * ErrorDesc() const { return errorDesc.c_str (); } 1183 1184 /** Generally, you probably want the error string ( ErrorDesc() ). But if you 1185 prefer the ErrorId, this function will fetch it. 1186 */ ErrorId()1187 int ErrorId() const { return errorId; } 1188 1189 /** Returns the location (if known) of the error. The first column is column 1, 1190 and the first row is row 1. A value of 0 means the row and column wasn't applicable 1191 (memory errors, for example, have no row/column) or the parser lost the error. (An 1192 error in the error reporting, in that case.) 1193 1194 @sa SetTabSize, Row, Column 1195 */ ErrorRow()1196 int ErrorRow() { return errorLocation.row+1; } ErrorCol()1197 int ErrorCol() { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() 1198 1199 /** By calling this method, with a tab size 1200 greater than 0, the row and column of each node and attribute is stored 1201 when the file is loaded. Very useful for tracking the DOM back in to 1202 the source file. 1203 1204 The tab size is required for calculating the location of nodes. If not 1205 set, the default of 4 is used. The tabsize is set per document. Setting 1206 the tabsize to 0 disables row/column tracking. 1207 1208 Note that row and column tracking is not supported when using operator>>. 1209 1210 The tab size needs to be enabled before the parse or load. Correct usage: 1211 @verbatim 1212 TiXmlDocument doc; 1213 doc.SetTabSize( 8 ); 1214 doc.Load( "myfile.xml" ); 1215 @endverbatim 1216 1217 @sa Row, Column 1218 */ SetTabSize(int _tabsize)1219 void SetTabSize( int _tabsize ) { tabsize = _tabsize; } 1220 TabSize()1221 int TabSize() const { return tabsize; } 1222 1223 /** If you have handled the error, it can be reset with this call. The error 1224 state is automatically cleared if you Parse a new XML block. 1225 */ ClearError()1226 void ClearError() { error = false; 1227 errorId = 0; 1228 errorDesc = ""; 1229 errorLocation.row = errorLocation.col = 0; 1230 //errorLocation.last = 0; 1231 } 1232 1233 /// Print this Document to a stream. 1234 virtual void Print( TIXML_OSTREAM& cfile, int depth = 0 ) const override; 1235 // [internal use] 1236 void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); 1237 1238 protected : 1239 virtual void StreamOut ( TIXML_OSTREAM * out) const override; 1240 // [internal use] 1241 virtual TiXmlNode* Clone() const override; 1242 #ifdef TIXML_USE_STL 1243 virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; 1244 #endif 1245 1246 private: 1247 void CopyTo( TiXmlDocument* target ) const; 1248 1249 bool error; 1250 int errorId; 1251 TIXML_STRING errorDesc; 1252 int tabsize; 1253 TiXmlCursor errorLocation; 1254 }; 1255 1256 1257 /** 1258 A TiXmlHandle is a class that wraps a node pointer with null checks; this is 1259 an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml 1260 DOM structure. It is a separate utility class. 1261 1262 Take an example: 1263 @verbatim 1264 <Document> 1265 <Element attributeA = "valueA"> 1266 <Child attributeB = "value1" /> 1267 <Child attributeB = "value2" /> 1268 </Element> 1269 <Document> 1270 @endverbatim 1271 1272 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 1273 easy to write a *lot* of code that looks like: 1274 1275 @verbatim 1276 TiXmlElement* root = document.FirstChildElement( "Document" ); 1277 if ( root ) 1278 { 1279 TiXmlElement* element = root->FirstChildElement( "Element" ); 1280 if ( element ) 1281 { 1282 TiXmlElement* child = element->FirstChildElement( "Child" ); 1283 if ( child ) 1284 { 1285 TiXmlElement* child2 = child->NextSiblingElement( "Child" ); 1286 if ( child2 ) 1287 { 1288 // Finally do something useful. 1289 @endverbatim 1290 1291 And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity 1292 of such code. A TiXmlHandle checks for null pointers so it is perfectly safe 1293 and correct to use: 1294 1295 @verbatim 1296 TiXmlHandle docHandle( &document ); 1297 TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element(); 1298 if ( child2 ) 1299 { 1300 // do something useful 1301 @endverbatim 1302 1303 Which is MUCH more concise and useful. 1304 1305 It is also safe to copy handles - internally they are nothing more than node pointers. 1306 @verbatim 1307 TiXmlHandle handleCopy = handle; 1308 @endverbatim 1309 1310 What they should not be used for is iteration: 1311 1312 @verbatim 1313 int i=0; 1314 while ( true ) 1315 { 1316 TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element(); 1317 if ( !child ) 1318 break; 1319 // do something 1320 ++i; 1321 } 1322 @endverbatim 1323 1324 It seems reasonable, but it is in fact two embedded while loops. The Child method is 1325 a linear walk to find the element, so this code would iterate much more than it needs 1326 to. Instead, prefer: 1327 1328 @verbatim 1329 TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element(); 1330 1331 for( child; child; child=child->NextSiblingElement() ) 1332 { 1333 // do something 1334 } 1335 @endverbatim 1336 */ 1337 class TiXmlHandle 1338 { 1339 public: 1340 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. TiXmlHandle(TiXmlNode * node)1341 TiXmlHandle( TiXmlNode* node ) { this->node = node; } 1342 /// Copy constructor TiXmlHandle(const TiXmlHandle & ref)1343 TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } 1344 TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } 1345 1346 /// Return a handle to the first child node. 1347 TiXmlHandle FirstChild() const; 1348 /// Return a handle to the first child node with the given name. 1349 TiXmlHandle FirstChild( const char * value ) const; 1350 /// Return a handle to the first child element. 1351 TiXmlHandle FirstChildElement() const; 1352 /// Return a handle to the first child element with the given name. 1353 TiXmlHandle FirstChildElement( const char * value ) const; 1354 1355 /** Return a handle to the "index" child with the given name. 1356 The first child is 0, the second 1, etc. 1357 */ 1358 TiXmlHandle Child( const char* value, int index ) const; 1359 /** Return a handle to the "index" child. 1360 The first child is 0, the second 1, etc. 1361 */ 1362 TiXmlHandle Child( int index ) const; 1363 /** Return a handle to the "index" child element with the given name. 1364 The first child element is 0, the second 1, etc. Note that only TiXmlElements 1365 are indexed: other types are not counted. 1366 */ 1367 TiXmlHandle ChildElement( const char* value, int index ) const; 1368 /** Return a handle to the "index" child element. 1369 The first child element is 0, the second 1, etc. Note that only TiXmlElements 1370 are indexed: other types are not counted. 1371 */ 1372 TiXmlHandle ChildElement( int index ) const; 1373 1374 #ifdef TIXML_USE_STL FirstChild(const std::string & _value)1375 TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } FirstChildElement(const std::string & _value)1376 TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } 1377 Child(const std::string & _value,int index)1378 TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } ChildElement(const std::string & _value,int index)1379 TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } 1380 #endif 1381 1382 /// Return the handle as a TiXmlNode. This may return null. Node()1383 TiXmlNode* Node() const { return node; } 1384 /// Return the handle as a TiXmlElement. This may return null. Element()1385 TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } 1386 /// Return the handle as a TiXmlText. This may return null. Text()1387 TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } 1388 /// Return the handle as a TiXmlUnknown. This may return null; Unknown()1389 TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } 1390 1391 private: 1392 TiXmlNode* node; 1393 }; 1394 1395 1396 #endif 1397 1398