2
www.sourceforge.net/projects/tinyxml
3
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
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.
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:
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.
18
2. Altered source versions must be plainly marked as such, and
19
must not be misrepresented as being the original software.
21
3. This notice may not be removed or altered from any source
25
#define TIXML_USE_STL 1
27
#ifndef TINYXML_INCLUDED
28
#define TINYXML_INCLUDED
31
#pragma warning( disable : 4530 )
32
#pragma warning( disable : 4786 )
42
#if defined( _DEBUG ) && !defined( DEBUG )
46
#if defined( DEBUG ) && defined( _MSC_VER )
48
#define TIXML_LOG OutputDebugString
50
#define TIXML_LOG printf
55
#define TIXML_STRING std::string
56
#define TIXML_ISTREAM std::istream
57
#define TIXML_OSTREAM std::ostream
65
class TiXmlDeclaration;
66
class TiXmlParsingData;
68
const int TIXML_MAJOR_VERSION = 2;
69
const int TIXML_MINOR_VERSION = 3;
70
const int TIXML_PATCH_VERSION = 4;
72
/* Internal structure for tracking location of items
77
TiXmlCursor() { Clear(); }
78
void Clear() { row = col = -1; }
85
// Only used by Attribute::Query functions
94
// Used by the parsing routines.
97
TIXML_ENCODING_UNKNOWN,
102
const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
104
/** TiXmlBase is a base class for every class in TinyXml.
105
It does little except to establish that TinyXml classes
106
can be printed and provide some utility functions.
108
In XML, the document and elements can contain
109
other elements and other types of nodes.
112
A Document can contain: Element (container or leaf)
117
An Element can contain: Element (container or leaf)
119
Attributes (not on tree)
123
A Decleration contains: Attributes (not on tree)
128
friend class TiXmlNode;
129
friend class TiXmlElement;
130
friend class TiXmlDocument;
133
TiXmlBase() : userData(0) {}
134
virtual ~TiXmlBase() {}
136
/** All TinyXml classes can print themselves to a filestream.
137
This is a formatted print, and will insert tabs and newlines.
139
(For an unformatted stream, use the << operator.)
141
virtual void Print( FILE* cfile, int depth ) const = 0;
143
/** The world does not agree on whether white space should be kept or
144
not. In order to make everyone happy, these global, static functions
145
are provided to set whether or not TinyXml will condense all white space
146
into a single space or not. The default is to condense. Note changing this
147
values is not thread safe.
149
static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
151
/// Return the current white space setting.
152
static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; }
154
/** Return the position, in the original source file, of this node or attribute.
155
The row and column are 1-based. (That is the first row and first column is
156
1,1). If the returns values are 0 or less, then the parser does not have
157
a row and column value.
159
Generally, the row and column value will be set when the TiXmlDocument::Load(),
160
TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
161
when the DOM was created from operator>>.
163
The values reflect the initial load. Once the DOM is modified programmatically
164
(by adding or changing nodes and attributes) the new values will NOT update to
165
reflect changes in the document.
167
There is a minor performance cost to computing the row and column. Computation
168
can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
170
@sa TiXmlDocument::SetTabSize()
172
int Row() const { return location.row + 1; }
173
int Column() const { return location.col + 1; } ///< See Row()
175
void SetUserData( void* user ) { userData = user; }
176
void* GetUserData() { return userData; }
178
// Table that returs, for a given lead byte, the total number of bytes
179
// in the UTF-8 sequence.
180
static const int utf8ByteTable[256];
182
virtual const char* Parse( const char* p,
183
TiXmlParsingData* data,
184
TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
190
TIXML_ERROR_OPENING_FILE,
191
TIXML_ERROR_OUT_OF_MEMORY,
192
TIXML_ERROR_PARSING_ELEMENT,
193
TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
194
TIXML_ERROR_READING_ELEMENT_VALUE,
195
TIXML_ERROR_READING_ATTRIBUTES,
196
TIXML_ERROR_PARSING_EMPTY,
197
TIXML_ERROR_READING_END_TAG,
198
TIXML_ERROR_PARSING_UNKNOWN,
199
TIXML_ERROR_PARSING_COMMENT,
200
TIXML_ERROR_PARSING_DECLARATION,
201
TIXML_ERROR_DOCUMENT_EMPTY,
202
TIXML_ERROR_EMBEDDED_NULL,
204
TIXML_ERROR_STRING_COUNT
209
// See STL_STRING_BUG
210
// Utility class to overcome a bug.
214
StringToBuffer( const TIXML_STRING& str );
219
static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
220
inline static bool IsWhiteSpace( char c )
222
return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
225
virtual void StreamOut (TIXML_OSTREAM *) const = 0;
228
static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
229
static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
232
/* Reads an XML name into the string provided. Returns
233
a pointer just past the last character of the name,
234
or 0 if the function has an error.
236
static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
238
/* Reads text. Returns a pointer past the given end tag.
239
Wickedly complex options, but it keeps the (sensitive) code in one place.
241
static const char* ReadText( const char* in, // where to start
242
TIXML_STRING* text, // the string read
243
bool ignoreWhiteSpace, // whether to keep the white space
244
const char* endTag, // what ends this text
245
bool ignoreCase, // whether to ignore case in the end tag
246
TiXmlEncoding encoding ); // the current encoding
248
// If an entity has been found, transform it into a character.
249
static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
251
// Get a character, while interpreting entities.
252
// The length can be from 0 to 4 bytes.
253
inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
256
if ( encoding == TIXML_ENCODING_UTF8 )
258
*length = utf8ByteTable[ *((unsigned char*)p) ];
259
assert( *length >= 0 && *length < 5 );
269
return GetEntity( p, _value, length, encoding );
275
strncpy( _value, p, *length );
276
return p + (*length);
285
// Puts a string to a stream, expanding entities as it goes.
286
// Note this should not contian the '<', '>', etc, or they will be transformed into entities!
287
static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
289
static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
291
// Return true if the next characters in the stream are any of the endTag sequences.
292
// Ignore case only works for english, and should only be relied on when comparing
293
// to Engilish words: StringEqual( p, "version", true ) is fine.
294
static bool StringEqual( const char* p,
297
TiXmlEncoding encoding );
299
static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
301
TiXmlCursor location;
303
/// Field containing a generic user pointer
306
// None of these methods are reliable for any language except English.
307
// Good for approximation, not great for accuracy.
308
static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
309
static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
310
inline static int ToLower( int v, TiXmlEncoding encoding )
312
if ( encoding == TIXML_ENCODING_UTF8 )
314
if ( v < 128 ) return tolower( v );
322
static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
325
TiXmlBase( const TiXmlBase& ); // not implemented.
326
void operator=( const TiXmlBase& base ); // not allowed.
331
unsigned int strLength;
337
MAX_ENTITY_LENGTH = 6
340
static Entity entity[ NUM_ENTITY ];
341
static bool condenseWhiteSpace;
345
/** The parent class for everything in the Document Object Model.
346
(Except for attributes).
347
Nodes have siblings, a parent, and children. A node can be
348
in a document, or stand on its own. The type of a TiXmlNode
349
can be queried, and it can be cast to its more defined type.
351
class TiXmlNode : public TiXmlBase
353
friend class TiXmlDocument;
354
friend class TiXmlElement;
359
/** An input stream operator, for every class. Tolerant of newlines and
360
formatting, but doesn't expect them.
362
friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
364
/** An output stream operator, for every class. Note that this outputs
365
without any newlines or formatting, as opposed to Print(), which
366
includes tabs and new lines.
368
The operator<< and operator>> are not completely symmetric. Writing
369
a node to a stream is very well defined. You'll get a nice stream
370
of output, without any extra whitespace or newlines.
372
But reading is not as well defined. (As it always is.) If you create
373
a TiXmlElement (for example) and read that from an input stream,
374
the text needs to define an element or junk will result. This is
375
true of all input streams, but it's worth keeping in mind.
377
A TiXmlDocument will read nodes until it reads a root element, and
378
all the children of that root element.
380
friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
382
/// Appends the XML node or attribute to a std::string.
383
friend std::string& operator<< (std::string& out, const TiXmlNode& base );
386
// Used internally, not part of the public API.
387
friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
390
/** The types of XML nodes supported by TinyXml. (All the
391
unsupported types are picked up by UNKNOWN.)
404
virtual ~TiXmlNode();
406
/** The meaning of 'value' changes for the specific type of
409
Document: filename of the xml file
410
Element: name of the element
411
Comment: the comment text
412
Unknown: the tag contents
413
Text: the text string
416
The subclasses will wrap this function.
418
const char * Value() const { return value.c_str (); }
420
/** Changes the value of the node. Defined as:
422
Document: filename of the xml file
423
Element: name of the element
424
Comment: the comment text
425
Unknown: the tag contents
426
Text: the text string
429
void SetValue(const char * _value) { value = _value;}
432
/// STL std::string form.
433
void SetValue( const std::string& _value )
435
StringToBuffer buf( _value );
436
SetValue( buf.buffer ? buf.buffer : "" );
440
/// Delete all the children of this node. Does not affect 'this'.
443
/// One step up the DOM.
444
TiXmlNode* Parent() { return parent; }
445
const TiXmlNode* Parent() const { return parent; }
447
const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
448
TiXmlNode* FirstChild() { return firstChild; }
449
const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
450
TiXmlNode* FirstChild( const char * value ); ///< The first child of this node with the matching 'value'. Will be null if none found.
452
const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
453
TiXmlNode* LastChild() { return lastChild; }
454
const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
455
TiXmlNode* LastChild( const char * value );
458
const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
459
TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
460
const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
461
TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form.
464
/** An alternate way to walk the children of a node.
465
One way to iterate over nodes is:
467
for( child = parent->FirstChild(); child; child = child->NextSibling() )
470
IterateChildren does the same thing with the syntax:
473
while( child = parent->IterateChildren( child ) )
476
IterateChildren takes the previous child as input and finds
477
the next one. If the previous child is null, it returns the
478
first. IterateChildren will return null when done.
480
const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
481
TiXmlNode* IterateChildren( TiXmlNode* previous );
483
/// This flavor of IterateChildren searches for children with a particular 'value'
484
const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
485
TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous );
488
const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
489
TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
492
/** Add a new node related to this. Adds a child past the LastChild.
493
Returns a pointer to the new object or NULL if an error occured.
495
TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
498
/** Add a new node related to this. Adds a child past the LastChild.
500
NOTE: the node to be added is passed by pointer, and will be
501
henceforth owned (and deleted) by tinyXml. This method is efficient
502
and avoids an extra copy, but should be used with care as it
503
uses a different memory model than the other insert functions.
507
TiXmlNode* LinkEndChild( TiXmlNode* addThis );
509
/** Add a new node related to this. Adds a child before the specified child.
510
Returns a pointer to the new object or NULL if an error occured.
512
TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
514
/** Add a new node related to this. Adds a child after the specified child.
515
Returns a pointer to the new object or NULL if an error occured.
517
TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
519
/** Replace a child of this node.
520
Returns a pointer to the new object or NULL if an error occured.
522
TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
524
/// Delete a child of this node.
525
bool RemoveChild( TiXmlNode* removeThis );
527
/// Navigate to a sibling node.
528
const TiXmlNode* PreviousSibling() const { return prev; }
529
TiXmlNode* PreviousSibling() { return prev; }
531
/// Navigate to a sibling node.
532
const TiXmlNode* PreviousSibling( const char * ) const;
533
TiXmlNode* PreviousSibling( const char * );
536
const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
537
TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
538
const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
539
TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form.
542
/// Navigate to a sibling node.
543
const TiXmlNode* NextSibling() const { return next; }
544
TiXmlNode* NextSibling() { return next; }
546
/// Navigate to a sibling node with the given 'value'.
547
const TiXmlNode* NextSibling( const char * ) const;
548
TiXmlNode* NextSibling( const char * );
550
/** Convenience function to get through elements.
551
Calls NextSibling and ToElement. Will skip all non-Element
552
nodes. Returns 0 if there is not another element.
554
const TiXmlElement* NextSiblingElement() const;
555
TiXmlElement* NextSiblingElement();
557
/** Convenience function to get through elements.
558
Calls NextSibling and ToElement. Will skip all non-Element
559
nodes. Returns 0 if there is not another element.
561
const TiXmlElement* NextSiblingElement( const char * ) const;
562
TiXmlElement* NextSiblingElement( const char * );
565
const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
566
TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
569
/// Convenience function to get through elements.
570
const TiXmlElement* FirstChildElement() const;
571
TiXmlElement* FirstChildElement();
573
/// Convenience function to get through elements.
574
const TiXmlElement* FirstChildElement( const char * value ) const;
575
TiXmlElement* FirstChildElement( const char * value );
578
const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
579
TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
582
/** Query the type (as an enumerated value, above) of this node.
583
The possible types are: DOCUMENT, ELEMENT, COMMENT,
584
UNKNOWN, TEXT, and DECLARATION.
586
virtual int Type() const { return type; }
588
/** Return a pointer to the Document this node lives in.
589
Returns null if not in a document.
591
const TiXmlDocument* GetDocument() const;
592
TiXmlDocument* GetDocument();
594
/// Returns true if this node has no children.
595
bool NoChildren() const { return !firstChild; }
597
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.
598
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.
599
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.
600
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.
601
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.
602
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.
604
TiXmlDocument* ToDocument() { return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
605
TiXmlElement* ToElement() { return ( this && type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
606
TiXmlComment* ToComment() { return ( this && type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
607
TiXmlUnknown* ToUnknown() { return ( this && type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
608
TiXmlText* ToText() { return ( this && type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
609
TiXmlDeclaration* ToDeclaration() { return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
611
/** Create an exact duplicate of this node and return it. The memory must be deleted
614
virtual TiXmlNode* Clone() const = 0;
617
TiXmlNode( NodeType _type );
619
// Copy to the allocated object. Shared functionality between Clone, Copy constructor,
620
// and the assignment operator.
621
void CopyTo( TiXmlNode* target ) const;
624
// The real work of the input operator.
625
virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
628
// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
629
TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
631
// Internal Value function returning a TIXML_STRING
632
const TIXML_STRING& SValue() const { return value ; }
637
TiXmlNode* firstChild;
638
TiXmlNode* lastChild;
646
TiXmlNode( const TiXmlNode& ); // not implemented.
647
void operator=( const TiXmlNode& base ); // not allowed.
651
/** An attribute is a name-value pair. Elements have an arbitrary
652
number of attributes, each with a unique name.
654
@note The attributes are not TiXmlNodes, since they are not
655
part of the tinyXML document object model. There are other
656
suggested ways to look at this problem.
658
class TiXmlAttribute : public TiXmlBase
660
friend class TiXmlAttributeSet;
663
/// Construct an empty attribute.
664
TiXmlAttribute() : TiXmlBase()
671
/// std::string constructor.
672
TiXmlAttribute( const std::string& _name, const std::string& _value )
681
/// Construct an attribute with a name and value.
682
TiXmlAttribute( const char * _name, const char * _value )
690
const char* Name() const { return name.c_str (); } ///< Return the name of this attribute.
691
const char* Value() const { return value.c_str (); } ///< Return the value of this attribute.
692
const int IntValue() const; ///< Return the value of this attribute, converted to an integer.
693
const double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
695
/** QueryIntValue examines the value string. It is an alternative to the
696
IntValue() method with richer error checking.
697
If the value is an integer, it is stored in 'value' and
698
the call returns TIXML_SUCCESS. If it is not
699
an integer, it returns TIXML_WRONG_TYPE.
701
A specialized but useful call. Note that for success it returns 0,
702
which is the opposite of almost all other TinyXml calls.
704
int QueryIntValue( int* value ) const;
705
/// QueryDoubleValue examines the value string. See QueryIntValue().
706
int QueryDoubleValue( double* value ) const;
708
void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
709
void SetValue( const char* _value ) { value = _value; } ///< Set the value.
711
void SetIntValue( int value ); ///< Set the value from an integer.
712
void SetDoubleValue( double value ); ///< Set the value from a double.
715
/// STL std::string form.
716
void SetName( const std::string& _name )
718
StringToBuffer buf( _name );
719
SetName ( buf.buffer ? buf.buffer : "error" );
721
/// STL std::string form.
722
void SetValue( const std::string& _value )
724
StringToBuffer buf( _value );
725
SetValue( buf.buffer ? buf.buffer : "error" );
729
/// Get the next sibling attribute in the DOM. Returns null at end.
730
const TiXmlAttribute* Next() const;
731
TiXmlAttribute* Next();
732
/// Get the previous sibling attribute in the DOM. Returns null at beginning.
733
const TiXmlAttribute* Previous() const;
734
TiXmlAttribute* Previous();
736
bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
737
bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
738
bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
740
/* Attribute parsing starts: first letter of the name
741
returns: the next char after the value end quote
743
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
745
// Prints this Attribute to a FILE stream.
746
virtual void Print( FILE* cfile, int depth ) const;
748
virtual void StreamOut( TIXML_OSTREAM * out ) const;
750
// Set the document pointer so the attribute can report errors.
751
void SetDocument( TiXmlDocument* doc ) { document = doc; }
754
TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
755
void operator=( const TiXmlAttribute& base ); // not allowed.
757
TiXmlDocument* document; // A pointer back to a document, for error reporting.
760
TiXmlAttribute* prev;
761
TiXmlAttribute* next;
765
/* A class used to manage a group of attributes.
766
It is only used internally, both by the ELEMENT and the DECLARATION.
768
The set can be changed transparent to the Element and Declaration
769
classes that use it, but NOT transparent to the Attribute
770
which has to implement a next() and previous() method. Which makes
771
it a bit problematic and prevents the use of STL.
773
This version is implemented with circular lists because:
774
- I like circular lists
775
- it demonstrates some independence from the (typical) doubly linked list.
777
class TiXmlAttributeSet
781
~TiXmlAttributeSet();
783
void Add( TiXmlAttribute* attribute );
784
void Remove( TiXmlAttribute* attribute );
786
const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
787
TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
788
const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
789
TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
791
const TiXmlAttribute* Find( const char * name ) const;
792
TiXmlAttribute* Find( const char * name );
795
//*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
796
//*ME: this class must be also use a hidden/disabled copy-constructor !!!
797
TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed
798
void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute)
800
TiXmlAttribute sentinel;
804
/** The element is a container class. It has a value, the element name,
805
and can contain other elements, text, comments, and unknowns.
806
Elements also contain an arbitrary number of attributes.
808
class TiXmlElement : public TiXmlNode
811
/// Construct an element.
812
TiXmlElement (const char * in_value);
815
/// std::string constructor.
816
TiXmlElement( const std::string& _value );
819
TiXmlElement( const TiXmlElement& );
821
void operator=( const TiXmlElement& base );
823
virtual ~TiXmlElement();
825
/** Given an attribute name, Attribute() returns the value
826
for the attribute of that name, or null if none exists.
828
const char* Attribute( const char* name ) const;
830
/** Given an attribute name, Attribute() returns the value
831
for the attribute of that name, or null if none exists.
832
If the attribute exists and can be converted to an integer,
833
the integer value will be put in the return 'i', if 'i'
836
const char* Attribute( const char* name, int* i ) const;
838
/** Given an attribute name, Attribute() returns the value
839
for the attribute of that name, or null if none exists.
840
If the attribute exists and can be converted to an double,
841
the double value will be put in the return 'd', if 'd'
844
const char* Attribute( const char* name, double* d ) const;
846
/** QueryIntAttribute examines the attribute - it is an alternative to the
847
Attribute() method with richer error checking.
848
If the attribute is an integer, it is stored in 'value' and
849
the call returns TIXML_SUCCESS. If it is not
850
an integer, it returns TIXML_WRONG_TYPE. If the attribute
851
does not exist, then TIXML_NO_ATTRIBUTE is returned.
853
int QueryIntAttribute( const char* name, int* value ) const;
854
/// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
855
int QueryDoubleAttribute( const char* name, double* value ) const;
856
/// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
857
int QueryDoubleAttribute( const char* name, float* value ) const {
859
int result = QueryDoubleAttribute( name, &d );
864
/** Sets an attribute of name to a given value. The attribute
865
will be created if it does not exist, or changed if it does.
867
void SetAttribute( const char* name, const char * value );
870
const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); }
871
const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); }
872
const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); }
873
int QueryIntAttribute( const std::string& name, int* value ) const { return QueryIntAttribute( name.c_str(), value ); }
874
int QueryDoubleAttribute( const std::string& name, double* value ) const { return QueryDoubleAttribute( name.c_str(), value ); }
876
/// STL std::string form.
877
void SetAttribute( const std::string& name, const std::string& _value )
879
StringToBuffer n( name );
880
StringToBuffer v( _value );
881
if ( n.buffer && v.buffer )
882
SetAttribute (n.buffer, v.buffer );
884
///< STL std::string form.
885
void SetAttribute( const std::string& name, int _value )
887
StringToBuffer n( name );
889
SetAttribute (n.buffer, _value);
893
/** Sets an attribute of name to a given value. The attribute
894
will be created if it does not exist, or changed if it does.
896
void SetAttribute( const char * name, int value );
898
/** Sets an attribute of name to a given value. The attribute
899
will be created if it does not exist, or changed if it does.
901
void SetDoubleAttribute( const char * name, double value );
903
/** Deletes an attribute with the given name.
905
void RemoveAttribute( const char * name );
907
void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
910
const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
911
TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
912
const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
913
TiXmlAttribute* LastAttribute() { return attributeSet.Last(); }
915
/// Creates a new Element and returns it - the returned element is a copy.
916
virtual TiXmlNode* Clone() const;
917
// Print the Element to a FILE stream.
918
virtual void Print( FILE* cfile, int depth ) const;
920
/* Attribtue parsing starts: next char past '<'
921
returns: next char past '>'
923
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
927
void CopyTo( TiXmlElement* target ) const;
928
void ClearThis(); // like clear, but initializes 'this' object as well
930
// Used to be public [internal use]
932
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
934
virtual void StreamOut( TIXML_OSTREAM * out ) const;
937
Reads the "value" of the element -- another element, or text.
938
This should terminate with the current end tag.
940
const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
944
TiXmlAttributeSet attributeSet;
950
class TiXmlComment : public TiXmlNode
953
/// Constructs an empty comment.
954
TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
955
TiXmlComment( const TiXmlComment& );
956
void operator=( const TiXmlComment& base );
958
virtual ~TiXmlComment() {}
960
/// Returns a copy of this Comment.
961
virtual TiXmlNode* Clone() const;
962
/// Write this Comment to a FILE stream.
963
virtual void Print( FILE* cfile, int depth ) const;
965
/* Attribtue parsing starts: at the ! of the !--
966
returns: next char past '>'
968
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
971
void CopyTo( TiXmlComment* target ) const;
975
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
977
virtual void StreamOut( TIXML_OSTREAM * out ) const;
984
/** XML text. Contained in an element.
986
class TiXmlText : public TiXmlNode
988
friend class TiXmlElement;
991
TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
993
SetValue( initValue );
995
virtual ~TiXmlText() {}
999
TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
1001
SetValue( initValue );
1005
TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); }
1006
void operator=( const TiXmlText& base ) { base.CopyTo( this ); }
1008
/// Write this text object to a FILE stream.
1009
virtual void Print( FILE* cfile, int depth ) const;
1011
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1014
/// [internal use] Creates a new Element and returns it.
1015
virtual TiXmlNode* Clone() const;
1016
void CopyTo( TiXmlText* target ) const;
1018
virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1019
bool Blank() const; // returns true if all white space and new lines
1021
#ifdef TIXML_USE_STL
1022
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1029
/** In correct XML the declaration is the first entry in the file.
1031
<?xml version="1.0" standalone="yes"?>
1034
TinyXml will happily read or write files without a declaration,
1035
however. There are 3 possible attributes to the declaration:
1036
version, encoding, and standalone.
1038
Note: In this version of the code, the attributes are
1039
handled as special cases, not generic attributes, simply
1040
because there can only be at most 3 and they are always the same.
1042
class TiXmlDeclaration : public TiXmlNode
1045
/// Construct an empty declaration.
1046
TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
1048
#ifdef TIXML_USE_STL
1050
TiXmlDeclaration( const std::string& _version,
1051
const std::string& _encoding,
1052
const std::string& _standalone );
1056
TiXmlDeclaration( const char* _version,
1057
const char* _encoding,
1058
const char* _standalone );
1060
TiXmlDeclaration( const TiXmlDeclaration& copy );
1061
void operator=( const TiXmlDeclaration& copy );
1063
virtual ~TiXmlDeclaration() {}
1065
/// Version. Will return an empty string if none was found.
1066
const char *Version() const { return version.c_str (); }
1067
/// Encoding. Will return an empty string if none was found.
1068
const char *Encoding() const { return encoding.c_str (); }
1069
/// Is this a standalone document?
1070
const char *Standalone() const { return standalone.c_str (); }
1072
/// Creates a copy of this Declaration and returns it.
1073
virtual TiXmlNode* Clone() const;
1074
/// Print this declaration to a FILE stream.
1075
virtual void Print( FILE* cfile, int depth ) const;
1077
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1080
void CopyTo( TiXmlDeclaration* target ) const;
1081
// used to be public
1082
#ifdef TIXML_USE_STL
1083
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1085
virtual void StreamOut ( TIXML_OSTREAM * out) const;
1089
TIXML_STRING version;
1090
TIXML_STRING encoding;
1091
TIXML_STRING standalone;
1095
/** Any tag that tinyXml doesn't recognize is saved as an
1096
unknown. It is a tag of text, but should not be modified.
1097
It will be written back to the XML, unchanged, when the file
1100
DTD tags get thrown into TiXmlUnknowns.
1102
class TiXmlUnknown : public TiXmlNode
1105
TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
1106
virtual ~TiXmlUnknown() {}
1108
TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); }
1109
void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); }
1111
/// Creates a copy of this Unknown and returns it.
1112
virtual TiXmlNode* Clone() const;
1113
/// Print this Unknown to a FILE stream.
1114
virtual void Print( FILE* cfile, int depth ) const;
1116
virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1119
void CopyTo( TiXmlUnknown* target ) const;
1121
#ifdef TIXML_USE_STL
1122
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1124
virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1131
/** Always the top level node. A document binds together all the
1132
XML pieces. It can be saved, loaded, and printed to the screen.
1133
The 'value' of a document node is the xml file name.
1135
class TiXmlDocument : public TiXmlNode
1138
/// Create an empty document, that has no name.
1140
/// Create a document with a name. The name of the document is also the filename of the xml.
1141
TiXmlDocument( const char * documentName );
1143
#ifdef TIXML_USE_STL
1145
TiXmlDocument( const std::string& documentName );
1148
TiXmlDocument( const TiXmlDocument& copy );
1149
void operator=( const TiXmlDocument& copy );
1151
virtual ~TiXmlDocument() {}
1153
/** Load a file using the current document value.
1154
Returns true if successful. Will delete any existing
1155
document data before loading.
1157
bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1158
/// Save a file using the current document value. Returns true if successful.
1159
bool SaveFile() const;
1160
/// Load a file using the given filename. Returns true if successful.
1161
bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1162
/// Save a file using the given filename. Returns true if successful.
1163
bool SaveFile( const char * filename ) const;
1165
#ifdef TIXML_USE_STL
1166
bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
1168
StringToBuffer f( filename );
1169
return ( f.buffer && LoadFile( f.buffer, encoding ));
1171
bool SaveFile( const std::string& filename ) const ///< STL std::string version.
1173
StringToBuffer f( filename );
1174
return ( f.buffer && SaveFile( f.buffer ));
1178
/** Parse the given null terminated block of xml data. Passing in an encoding to this
1179
method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
1180
to use that encoding, regardless of what TinyXml might otherwise try to detect.
1182
virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1184
/** Get the root element -- the only top level element -- of the document.
1185
In well formed XML, there should only be one. TinyXml is tolerant of
1186
multiple elements at the document level.
1188
const TiXmlElement* RootElement() const { return FirstChildElement(); }
1189
TiXmlElement* RootElement() { return FirstChildElement(); }
1191
/** If an error occurs, Error will be set to true. Also,
1192
- The ErrorId() will contain the integer identifier of the error (not generally useful)
1193
- The ErrorDesc() method will return the name of the error. (very useful)
1194
- The ErrorRow() and ErrorCol() will return the location of the error (if known)
1196
bool Error() const { return error; }
1198
/// Contains a textual (english) description of the error if one occurs.
1199
const char * ErrorDesc() const { return errorDesc.c_str (); }
1201
/** Generally, you probably want the error string ( ErrorDesc() ). But if you
1202
prefer the ErrorId, this function will fetch it.
1204
const int ErrorId() const { return errorId; }
1206
/** Returns the location (if known) of the error. The first column is column 1,
1207
and the first row is row 1. A value of 0 means the row and column wasn't applicable
1208
(memory errors, for example, have no row/column) or the parser lost the error. (An
1209
error in the error reporting, in that case.)
1211
@sa SetTabSize, Row, Column
1213
int ErrorRow() { return errorLocation.row+1; }
1214
int ErrorCol() { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
1216
/** By calling this method, with a tab size
1217
greater than 0, the row and column of each node and attribute is stored
1218
when the file is loaded. Very useful for tracking the DOM back in to
1221
The tab size is required for calculating the location of nodes. If not
1222
set, the default of 4 is used. The tabsize is set per document. Setting
1223
the tabsize to 0 disables row/column tracking.
1225
Note that row and column tracking is not supported when using operator>>.
1227
The tab size needs to be enabled before the parse or load. Correct usage:
1230
doc.SetTabSize( 8 );
1231
doc.Load( "myfile.xml" );
1236
void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
1238
int TabSize() const { return tabsize; }
1240
/** If you have handled the error, it can be reset with this call. The error
1241
state is automatically cleared if you Parse a new XML block.
1243
void ClearError() { error = false;
1246
errorLocation.row = errorLocation.col = 0;
1247
//errorLocation.last = 0;
1250
/** Dump the document to standard out. */
1251
void Print() const { Print( stdout, 0 ); }
1253
/// Print this Document to a FILE stream.
1254
virtual void Print( FILE* cfile, int depth = 0 ) const;
1256
void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
1259
virtual void StreamOut ( TIXML_OSTREAM * out) const;
1261
virtual TiXmlNode* Clone() const;
1262
#ifdef TIXML_USE_STL
1263
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1267
void CopyTo( TiXmlDocument* target ) const;
1271
TIXML_STRING errorDesc;
1273
TiXmlCursor errorLocation;
1278
A TiXmlHandle is a class that wraps a node pointer with null checks; this is
1279
an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
1280
DOM structure. It is a separate utility class.
1285
<Element attributeA = "valueA">
1286
<Child attributeB = "value1" />
1287
<Child attributeB = "value2" />
1292
Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1293
easy to write a *lot* of code that looks like:
1296
TiXmlElement* root = document.FirstChildElement( "Document" );
1299
TiXmlElement* element = root->FirstChildElement( "Element" );
1302
TiXmlElement* child = element->FirstChildElement( "Child" );
1305
TiXmlElement* child2 = child->NextSiblingElement( "Child" );
1308
// Finally do something useful.
1311
And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
1312
of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
1316
TiXmlHandle docHandle( &document );
1317
TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
1320
// do something useful
1323
Which is MUCH more concise and useful.
1325
It is also safe to copy handles - internally they are nothing more than node pointers.
1327
TiXmlHandle handleCopy = handle;
1330
What they should not be used for is iteration:
1336
TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
1344
It seems reasonable, but it is in fact two embedded while loops. The Child method is
1345
a linear walk to find the element, so this code would iterate much more than it needs
1346
to. Instead, prefer:
1349
TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
1351
for( child; child; child=child->NextSiblingElement() )
1360
/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1361
TiXmlHandle( TiXmlNode* node ) { this->node = node; }
1362
/// Copy constructor
1363
TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
1364
TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
1366
/// Return a handle to the first child node.
1367
TiXmlHandle FirstChild() const;
1368
/// Return a handle to the first child node with the given name.
1369
TiXmlHandle FirstChild( const char * value ) const;
1370
/// Return a handle to the first child element.
1371
TiXmlHandle FirstChildElement() const;
1372
/// Return a handle to the first child element with the given name.
1373
TiXmlHandle FirstChildElement( const char * value ) const;
1375
/** Return a handle to the "index" child with the given name.
1376
The first child is 0, the second 1, etc.
1378
TiXmlHandle Child( const char* value, int index ) const;
1379
/** Return a handle to the "index" child.
1380
The first child is 0, the second 1, etc.
1382
TiXmlHandle Child( int index ) const;
1383
/** Return a handle to the "index" child element with the given name.
1384
The first child element is 0, the second 1, etc. Note that only TiXmlElements
1385
are indexed: other types are not counted.
1387
TiXmlHandle ChildElement( const char* value, int index ) const;
1388
/** Return a handle to the "index" child element.
1389
The first child element is 0, the second 1, etc. Note that only TiXmlElements
1390
are indexed: other types are not counted.
1392
TiXmlHandle ChildElement( int index ) const;
1394
#ifdef TIXML_USE_STL
1395
TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
1396
TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
1398
TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); }
1399
TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); }
1402
/// Return the handle as a TiXmlNode. This may return null.
1403
TiXmlNode* Node() const { return node; }
1404
/// Return the handle as a TiXmlElement. This may return null.
1405
TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1406
/// Return the handle as a TiXmlText. This may return null.
1407
TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1408
/// Return the handle as a TiXmlUnknown. This may return null;
1409
TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1416
#pragma warning( default : 4530 )
1417
#pragma warning( default : 4786 )