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