blob: 18cf94f172ed15124600ca602ba81e9527dad425 [file] [log] [blame]
The Android Open Source Project562be062009-03-03 19:30:48 -08001/*
2www.sourceforge.net/projects/tinyxml
3Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
4
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any
7damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any
10purpose, including commercial applications, and to alter it and
11redistribute it freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must
14not claim that you wrote the original software. If you use this
15software in a product, an acknowledgment in the product documentation
16would be appreciated but is not required.
17
182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
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
85class TiXmlDocument;
86class TiXmlElement;
87class TiXmlComment;
88class TiXmlUnknown;
89class TiXmlAttribute;
90class TiXmlText;
91class TiXmlDeclaration;
92class TiXmlParsingData;
93
94const int TIXML_MAJOR_VERSION = 2;
95const int TIXML_MINOR_VERSION = 4;
96const int TIXML_PATCH_VERSION = 0;
97
98/* Internal structure for tracking location of items
99 in the XML file.
100*/
101struct TiXmlCursor
102{
103 TiXmlCursor() { Clear(); }
104 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
112enum
113{
114 TIXML_SUCCESS,
115 TIXML_NO_ATTRIBUTE,
116 TIXML_WRONG_TYPE
117};
118
119
120// Used by the parsing routines.
121enum TiXmlEncoding
122{
123 TIXML_ENCODING_UNKNOWN,
124 TIXML_ENCODING_UTF8,
125 TIXML_ENCODING_LEGACY
126};
127
128const 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*/
152class TiXmlBase
153{
154 friend class TiXmlNode;
155 friend class TiXmlElement;
156 friend class TiXmlDocument;
157
158public:
159 TiXmlBase() : userData(0) {}
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 */
175 static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
176
177 /// Return the current white space setting.
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 */
198 int Row() const { return location.row + 1; }
199 int Column() const { return location.col + 1; } ///< See Row()
200
201 void SetUserData( void* user ) { userData = user; }
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
234protected:
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 );
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.
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 );
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
355private:
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*/
382class TiXmlNode : public TiXmlBase
383{
384 friend class TiXmlDocument;
385 friend class TiXmlElement;
386
387public:
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 */
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 */
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 */
468 void SetValue(const char * _value) { value = _value;}
469
470 #ifdef TIXML_USE_STL
471 /// STL std::string form.
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.
483 TiXmlNode* Parent() { return parent; }
484 const TiXmlNode* Parent() const { return parent; }
485
486 const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
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
491 const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
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
497 const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
498 TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
499 const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
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
527 const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
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.
567 const TiXmlNode* PreviousSibling() const { return prev; }
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
575 const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
576 TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
577 const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
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.
582 const TiXmlNode* NextSibling() const { return next; }
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
604 const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
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
617 const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
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 */
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.
634 bool NoChildren() const { return !firstChild; }
635
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.
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.
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.
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.
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.
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
643 TiXmlDocument* ToDocument() { return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
644 TiXmlElement* ToElement() { return ( this && type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
645 TiXmlComment* ToComment() { return ( this && type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
646 TiXmlUnknown* ToUnknown() { return ( this && type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
647 TiXmlText* ToText() { return ( this && type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
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
655protected:
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
681private:
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*/
694class TiXmlAttribute : public TiXmlBase
695{
696 friend class TiXmlAttributeSet;
697
698public:
699 /// Construct an empty attribute.
700 TiXmlAttribute() : TiXmlBase()
701 {
702 document = 0;
703 prev = next = 0;
704 }
705
706 #ifdef TIXML_USE_STL
707 /// std::string constructor.
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.
718 TiXmlAttribute( const char * _name, const char * _value )
719 {
720 name = _name;
721 value = _value;
722 document = 0;
723 prev = next = 0;
724 }
725
726 const char* Name() const { return name.c_str (); } ///< Return the name of this attribute.
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
744 void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
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.
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.
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.
787 void SetDocument( TiXmlDocument* doc ) { document = doc; }
788
789private:
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*/
813class TiXmlAttributeSet
814{
815public:
816 TiXmlAttributeSet();
817 ~TiXmlAttributeSet();
818
819 void Add( TiXmlAttribute* attribute );
820 void Remove( TiXmlAttribute* attribute );
821
822 const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
823 TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
824 const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
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
830private:
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*/
844class TiXmlElement : public TiXmlNode
845{
846public:
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().
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
908 const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); }
909 const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); }
910 const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); }
911 int QueryIntAttribute( const std::string& name, int* _value ) const { return QueryIntAttribute( name.c_str(), _value ); }
912 int QueryDoubleAttribute( const std::string& name, double* _value ) const { return QueryDoubleAttribute( name.c_str(), _value ); }
913
914 /// STL std::string form.
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.
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
945 void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
946 #endif
947
948 const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
949 TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
950 const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
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
997protected:
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
1014private:
1015
1016 TiXmlAttributeSet attributeSet;
1017};
1018
1019
1020/** An XML comment.
1021*/
1022class TiXmlComment : public TiXmlNode
1023{
1024public:
1025 /// Constructs an empty comment.
1026 TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
1027 TiXmlComment( const TiXmlComment& );
1028 void operator=( const TiXmlComment& base );
1029
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
1042protected:
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
1051private:
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*/
1061class TiXmlText : public TiXmlNode
1062{
1063 friend class TiXmlElement;
1064public:
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 */
1069 TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
1070 {
1071 SetValue( initValue );
1072 cdata = false;
1073 }
1074 virtual ~TiXmlText() {}
1075
1076 #ifdef TIXML_USE_STL
1077 /// Constructor.
1078 TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
1079 {
1080 SetValue( initValue );
1081 cdata = false;
1082 }
1083 #endif
1084
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.
1092 bool CDATA() { return cdata; }
1093 /// Turns on or off a CDATA representation of text.
1094 void SetCDATA( bool _cdata ) { cdata = _cdata; }
1095
1096 virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1097
1098protected :
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
1110private:
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*/
1128class TiXmlDeclaration : public TiXmlNode
1129{
1130public:
1131 /// Construct an empty declaration.
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
1149 virtual ~TiXmlDeclaration() {}
1150
1151 /// Version. Will return an empty string if none was found.
1152 const char *Version() const { return version.c_str (); }
1153 /// Encoding. Will return an empty string if none was found.
1154 const char *Encoding() const { return encoding.c_str (); }
1155 /// Is this a standalone document?
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
1165protected:
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
1173private:
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*/
1188class TiXmlUnknown : public TiXmlNode
1189{
1190public:
1191 TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
1192 virtual ~TiXmlUnknown() {}
1193
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
1204protected:
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
1212private:
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*/
1221class TiXmlDocument : public TiXmlNode
1222{
1223public:
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
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 }
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 */
1274 const TiXmlElement* RootElement() const { return FirstChildElement(); }
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 */
1282 bool Error() const { return error; }
1283
1284 /// Contains a textual (english) description of the error if one occurs.
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 */
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 */
1299 int ErrorRow() { return errorLocation.row+1; }
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 */
1326 void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
1327
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 */
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. */
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
1348protected :
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
1356private:
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*/
1448class TiXmlHandle
1449{
1450public:
1451 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1452 TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
1453 /// Copy constructor
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
1486 TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
1487 TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
1488
1489 TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), 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.
1494 TiXmlNode* Node() const { return node; }
1495 /// Return the handle as a TiXmlElement. This may return null.
1496 TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1497 /// Return the handle as a TiXmlText. This may return null.
1498 TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1499 /// Return the handle as a TiXmlUnknown. This may return null;
1500 TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1501
1502private:
1503 TiXmlNode* node;
1504};
1505
1506#ifdef _MSC_VER
1507#pragma warning( pop )
1508#endif
1509
1510#endif
1511