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