stratgame

view level/src/tinyxml2.h @ 0:86b53f76899f

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 21 May 2012 19:07:40 +0300
parents
children
line source
1 /*
2 Original code by Lee Thomason (www.grinninglizard.com)
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any
6 damages arising from the use of this software.
8 Permission is granted to anyone to use this software for any
9 purpose, including commercial applications, and to alter it and
10 redistribute it freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and
18 must not be misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source
21 distribution.
22 */
24 #ifndef TINYXML2_INCLUDED
25 #define TINYXML2_INCLUDED
27 #include <cctype>
28 #include <climits>
29 #include <cstdio>
30 #include <cstring>
31 #include <cstdarg>
33 /*
34 TODO: intern strings instead of allocation.
35 */
36 /*
37 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
38 */
40 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
41 #ifndef DEBUG
42 #define DEBUG
43 #endif
44 #endif
47 #if defined(DEBUG)
48 #if defined(_MSC_VER)
49 #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
50 #elif defined (ANDROID_NDK)
51 #include <android/log.h>
52 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
53 #else
54 #include <assert.h>
55 #define TIXMLASSERT assert
56 #endif
57 #else
58 #define TIXMLASSERT( x ) {}
59 #endif
62 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
63 // Microsoft visual studio, version 2005 and higher.
64 /*int _snprintf_s(
65 char *buffer,
66 size_t sizeOfBuffer,
67 size_t count,
68 const char *format [,
69 argument] ...
70 );*/
71 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
72 va_list va;
73 va_start( va, format );
74 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
75 va_end( va );
76 return result;
77 }
78 #define TIXML_SSCANF sscanf_s
79 #else
80 // GCC version 3 and higher
81 //#warning( "Using sn* functions." )
82 #define TIXML_SNPRINTF snprintf
83 #define TIXML_SSCANF sscanf
84 #endif
86 static const int TIXML2_MAJOR_VERSION = 1;
87 static const int TIXML2_MINOR_VERSION = 0;
88 static const int TIXML2_PATCH_VERSION = 1;
90 namespace tinyxml2
91 {
92 class XMLDocument;
93 class XMLElement;
94 class XMLAttribute;
95 class XMLComment;
96 class XMLNode;
97 class XMLText;
98 class XMLDeclaration;
99 class XMLUnknown;
101 class XMLPrinter;
103 /*
104 A class that wraps strings. Normally stores the start and end
105 pointers into the XML file itself, and will apply normalization
106 and entity translation if actually read. Can also store (and memory
107 manage) a traditional char[]
108 */
109 class StrPair
110 {
111 public:
112 enum {
113 NEEDS_ENTITY_PROCESSING = 0x01,
114 NEEDS_NEWLINE_NORMALIZATION = 0x02,
116 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
117 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
118 ATTRIBUTE_NAME = 0,
119 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
120 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
121 COMMENT = NEEDS_NEWLINE_NORMALIZATION
122 };
124 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
125 ~StrPair();
127 void Set( char* _start, char* _end, int _flags ) {
128 Reset();
129 this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
130 }
131 const char* GetStr();
132 bool Empty() const { return start == end; }
134 void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
135 void SetStr( const char* str, int flags=0 );
137 char* ParseText( char* in, const char* endTag, int strFlags );
138 char* ParseName( char* in );
141 private:
142 void Reset();
144 enum {
145 NEEDS_FLUSH = 0x100,
146 NEEDS_DELETE = 0x200
147 };
149 // After parsing, if *end != 0, it can be set to zero.
150 int flags;
151 char* start;
152 char* end;
153 };
156 /*
157 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
158 Has a small initial memory pool, so that low or no usage will not
159 cause a call to new/delete
160 */
161 template <class T, int INIT>
162 class DynArray
163 {
164 public:
165 DynArray< T, INIT >()
166 {
167 mem = pool;
168 allocated = INIT;
169 size = 0;
170 }
171 ~DynArray()
172 {
173 if ( mem != pool ) {
174 delete [] mem;
175 }
176 }
177 void Push( T t )
178 {
179 EnsureCapacity( size+1 );
180 mem[size++] = t;
181 }
183 T* PushArr( int count )
184 {
185 EnsureCapacity( size+count );
186 T* ret = &mem[size];
187 size += count;
188 return ret;
189 }
190 T Pop() {
191 return mem[--size];
192 }
193 void PopArr( int count )
194 {
195 TIXMLASSERT( size >= count );
196 size -= count;
197 }
199 bool Empty() const { return size == 0; }
200 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
201 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
202 int Size() const { return size; }
203 int Capacity() const { return allocated; }
204 const T* Mem() const { return mem; }
205 T* Mem() { return mem; }
208 private:
209 void EnsureCapacity( int cap ) {
210 if ( cap > allocated ) {
211 int newAllocated = cap * 2;
212 T* newMem = new T[newAllocated];
213 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
214 if ( mem != pool ) delete [] mem;
215 mem = newMem;
216 allocated = newAllocated;
217 }
218 }
220 T* mem;
221 T pool[INIT];
222 int allocated; // objects allocated
223 int size; // number objects in use
224 };
227 /*
228 Parent virtual class of a pool for fast allocation
229 and deallocation of objects.
230 */
231 class MemPool
232 {
233 public:
234 MemPool() {}
235 virtual ~MemPool() {}
237 virtual int ItemSize() const = 0;
238 virtual void* Alloc() = 0;
239 virtual void Free( void* ) = 0;
240 };
243 /*
244 Template child class to create pools of the correct type.
245 */
246 template< int SIZE >
247 class MemPoolT : public MemPool
248 {
249 public:
250 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
251 ~MemPoolT() {
252 // Delete the blocks.
253 for( int i=0; i<blockPtrs.Size(); ++i ) {
254 delete blockPtrs[i];
255 }
256 }
258 virtual int ItemSize() const { return SIZE; }
259 int CurrentAllocs() const { return currentAllocs; }
261 virtual void* Alloc() {
262 if ( !root ) {
263 // Need a new block.
264 Block* block = new Block();
265 blockPtrs.Push( block );
267 for( int i=0; i<COUNT-1; ++i ) {
268 block->chunk[i].next = &block->chunk[i+1];
269 }
270 block->chunk[COUNT-1].next = 0;
271 root = block->chunk;
272 }
273 void* result = root;
274 root = root->next;
276 ++currentAllocs;
277 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
278 nAllocs++;
279 return result;
280 }
281 virtual void Free( void* mem ) {
282 if ( !mem ) return;
283 --currentAllocs;
284 Chunk* chunk = (Chunk*)mem;
285 memset( chunk, 0xfe, sizeof(Chunk) );
286 chunk->next = root;
287 root = chunk;
288 }
289 void Trace( const char* name ) {
290 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
291 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
292 }
294 private:
295 enum { COUNT = 1024/SIZE };
296 union Chunk {
297 Chunk* next;
298 char mem[SIZE];
299 };
300 struct Block {
301 Chunk chunk[COUNT];
302 };
303 DynArray< Block*, 10 > blockPtrs;
304 Chunk* root;
306 int currentAllocs;
307 int nAllocs;
308 int maxAllocs;
309 };
313 /**
314 Implements the interface to the "Visitor pattern" (see the Accept() method.)
315 If you call the Accept() method, it requires being passed a XMLVisitor
316 class to handle callbacks. For nodes that contain other nodes (Document, Element)
317 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
318 are simply called with Visit().
320 If you return 'true' from a Visit method, recursive parsing will continue. If you return
321 false, <b>no children of this node or its sibilings</b> will be visited.
323 All flavors of Visit methods have a default implementation that returns 'true' (continue
324 visiting). You need to only override methods that are interesting to you.
326 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
328 You should never change the document from a callback.
330 @sa XMLNode::Accept()
331 */
332 class XMLVisitor
333 {
334 public:
335 virtual ~XMLVisitor() {}
337 /// Visit a document.
338 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
339 /// Visit a document.
340 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
342 /// Visit an element.
343 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
344 /// Visit an element.
345 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
347 /// Visit a declaration.
348 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
349 /// Visit a text node.
350 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
351 /// Visit a comment node.
352 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
353 /// Visit an unknown node.
354 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
355 };
358 /*
359 Utility functionality.
360 */
361 class XMLUtil
362 {
363 public:
364 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
365 // correct, but simple, and usually works.
366 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
367 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
369 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
370 int n = 0;
371 if ( p == q ) {
372 return true;
373 }
374 while( *p && *q && *p == *q && n<nChar ) {
375 ++p; ++q; ++n;
376 }
377 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
378 return true;
379 }
380 return false;
381 }
382 inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
383 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
384 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
386 static const char* ReadBOM( const char* p, bool* hasBOM );
387 // p is the starting location,
388 // the UTF-8 value of the entity will be placed in value, and length filled in.
389 static const char* GetCharacterRef( const char* p, char* value, int* length );
390 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
391 };
394 /** XMLNode is a base class for every object that is in the
395 XML Document Object Model (DOM), except XMLAttributes.
396 Nodes have siblings, a parent, and children which can
397 be navigated. A node is always in a XMLDocument.
398 The type of a XMLNode can be queried, and it can
399 be cast to its more defined type.
401 A XMLDocument allocates memory for all its Nodes.
402 When the XMLDocument gets deleted, all its Nodes
403 will also be deleted.
405 @verbatim
406 A Document can contain: Element (container or leaf)
407 Comment (leaf)
408 Unknown (leaf)
409 Declaration( leaf )
411 An Element can contain: Element (container or leaf)
412 Text (leaf)
413 Attributes (not on tree)
414 Comment (leaf)
415 Unknown (leaf)
417 @endverbatim
418 */
419 class XMLNode
420 {
421 friend class XMLDocument;
422 friend class XMLElement;
423 public:
425 /// Get the XMLDocument that owns this XMLNode.
426 const XMLDocument* GetDocument() const { return document; }
427 /// Get the XMLDocument that owns this XMLNode.
428 XMLDocument* GetDocument() { return document; }
430 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
431 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
432 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
433 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
434 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
435 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
437 virtual const XMLElement* ToElement() const { return 0; }
438 virtual const XMLText* ToText() const { return 0; }
439 virtual const XMLComment* ToComment() const { return 0; }
440 virtual const XMLDocument* ToDocument() const { return 0; }
441 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
442 virtual const XMLUnknown* ToUnknown() const { return 0; }
444 /** The meaning of 'value' changes for the specific type.
445 @verbatim
446 Document: empty
447 Element: name of the element
448 Comment: the comment text
449 Unknown: the tag contents
450 Text: the text string
451 @endverbatim
452 */
453 const char* Value() const { return value.GetStr(); }
454 /** Set the Value of an XML node.
455 @sa Value()
456 */
457 void SetValue( const char* val, bool staticMem=false );
459 /// Get the parent of this node on the DOM.
460 const XMLNode* Parent() const { return parent; }
461 XMLNode* Parent() { return parent; }
463 /// Returns true if this node has no children.
464 bool NoChildren() const { return !firstChild; }
466 /// Get the first child node, or null if none exists.
467 const XMLNode* FirstChild() const { return firstChild; }
468 XMLNode* FirstChild() { return firstChild; }
469 /** Get the first child element, or optionally the first child
470 element with the specified name.
471 */
472 const XMLElement* FirstChildElement( const char* value=0 ) const;
473 XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
475 /// Get the last child node, or null if none exists.
476 const XMLNode* LastChild() const { return lastChild; }
477 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
479 /** Get the last child element or optionally the last child
480 element with the specified name.
481 */
482 const XMLElement* LastChildElement( const char* value=0 ) const;
483 XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
485 /// Get the previous (left) sibling node of this node.
486 const XMLNode* PreviousSibling() const { return prev; }
487 XMLNode* PreviousSibling() { return prev; }
489 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
490 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
491 XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
493 /// Get the next (right) sibling node of this node.
494 const XMLNode* NextSibling() const { return next; }
495 XMLNode* NextSibling() { return next; }
497 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
498 const XMLElement* NextSiblingElement( const char* value=0 ) const;
499 XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
501 /**
502 Add a child node as the last (right) child.
503 */
504 XMLNode* InsertEndChild( XMLNode* addThis );
506 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
507 /**
508 Add a child node as the first (left) child.
509 */
510 XMLNode* InsertFirstChild( XMLNode* addThis );
511 /**
512 Add a node after the specified child node.
513 */
514 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
516 /**
517 Delete all the children of this node.
518 */
519 void DeleteChildren();
521 /**
522 Delete a child of this node.
523 */
524 void DeleteChild( XMLNode* node );
526 /**
527 Make a copy of this node, but not its children.
528 You may pass in a Document pointer that will be
529 the owner of the new Node. If the 'document' is
530 null, then the node returned will be allocated
531 from the current Document. (this->GetDocument())
533 Note: if called on a XMLDocument, this will return null.
534 */
535 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
537 /**
538 Test if 2 nodes are the same, but don't test children.
539 The 2 nodes do not need to be in the same Document.
541 Note: if called on a XMLDocument, this will return false.
542 */
543 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
545 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
546 XML tree will be conditionally visited and the host will be called back
547 via the TiXmlVisitor interface.
549 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
550 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
551 interface versus any other.)
553 The interface has been based on ideas from:
555 - http://www.saxproject.org/
556 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
558 Which are both good references for "visiting".
560 An example of using Accept():
561 @verbatim
562 TiXmlPrinter printer;
563 tinyxmlDoc.Accept( &printer );
564 const char* xmlcstr = printer.CStr();
565 @endverbatim
566 */
567 virtual bool Accept( XMLVisitor* visitor ) const = 0;
569 // internal
570 virtual char* ParseDeep( char*, StrPair* );
572 protected:
573 XMLNode( XMLDocument* );
574 virtual ~XMLNode();
575 XMLNode( const XMLNode& ); // not supported
576 void operator=( const XMLNode& ); // not supported
578 XMLDocument* document;
579 XMLNode* parent;
580 mutable StrPair value;
582 XMLNode* firstChild;
583 XMLNode* lastChild;
585 XMLNode* prev;
586 XMLNode* next;
588 private:
589 MemPool* memPool;
590 void Unlink( XMLNode* child );
591 };
594 /** XML text.
596 Note that a text node can have child element nodes, for example:
597 @verbatim
598 <root>This is <b>bold</b></root>
599 @endverbatim
601 A text node can have 2 ways to output the next. "normal" output
602 and CDATA. It will default to the mode it was parsed from the XML file and
603 you generally want to leave it alone, but you can change the output mode with
604 SetCDATA() and query it with CDATA().
605 */
606 class XMLText : public XMLNode
607 {
608 friend class XMLBase;
609 friend class XMLDocument;
610 public:
611 virtual bool Accept( XMLVisitor* visitor ) const;
613 virtual XMLText* ToText() { return this; }
614 virtual const XMLText* ToText() const { return this; }
616 /// Declare whether this should be CDATA or standard text.
617 void SetCData( bool _isCData ) { this->isCData = _isCData; }
618 /// Returns true if this is a CDATA text element.
619 bool CData() const { return isCData; }
621 char* ParseDeep( char*, StrPair* endTag );
622 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
623 virtual bool ShallowEqual( const XMLNode* compare ) const;
626 protected:
627 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
628 virtual ~XMLText() {}
629 XMLText( const XMLText& ); // not supported
630 void operator=( const XMLText& ); // not supported
632 private:
633 bool isCData;
634 };
637 /** An XML Comment. */
638 class XMLComment : public XMLNode
639 {
640 friend class XMLDocument;
641 public:
642 virtual XMLComment* ToComment() { return this; }
643 virtual const XMLComment* ToComment() const { return this; }
645 virtual bool Accept( XMLVisitor* visitor ) const;
647 char* ParseDeep( char*, StrPair* endTag );
648 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
649 virtual bool ShallowEqual( const XMLNode* compare ) const;
651 protected:
652 XMLComment( XMLDocument* doc );
653 virtual ~XMLComment();
654 XMLComment( const XMLComment& ); // not supported
655 void operator=( const XMLComment& ); // not supported
657 private:
658 };
661 /** In correct XML the declaration is the first entry in the file.
662 @verbatim
663 <?xml version="1.0" standalone="yes"?>
664 @endverbatim
666 TinyXML2 will happily read or write files without a declaration,
667 however.
669 The text of the declaration isn't interpreted. It is parsed
670 and written as a string.
671 */
672 class XMLDeclaration : public XMLNode
673 {
674 friend class XMLDocument;
675 public:
676 virtual XMLDeclaration* ToDeclaration() { return this; }
677 virtual const XMLDeclaration* ToDeclaration() const { return this; }
679 virtual bool Accept( XMLVisitor* visitor ) const;
681 char* ParseDeep( char*, StrPair* endTag );
682 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
683 virtual bool ShallowEqual( const XMLNode* compare ) const;
685 protected:
686 XMLDeclaration( XMLDocument* doc );
687 virtual ~XMLDeclaration();
688 XMLDeclaration( const XMLDeclaration& ); // not supported
689 void operator=( const XMLDeclaration& ); // not supported
690 };
693 /** Any tag that tinyXml doesn't recognize is saved as an
694 unknown. It is a tag of text, but should not be modified.
695 It will be written back to the XML, unchanged, when the file
696 is saved.
698 DTD tags get thrown into TiXmlUnknowns.
699 */
700 class XMLUnknown : public XMLNode
701 {
702 friend class XMLDocument;
703 public:
704 virtual XMLUnknown* ToUnknown() { return this; }
705 virtual const XMLUnknown* ToUnknown() const { return this; }
707 virtual bool Accept( XMLVisitor* visitor ) const;
709 char* ParseDeep( char*, StrPair* endTag );
710 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
711 virtual bool ShallowEqual( const XMLNode* compare ) const;
713 protected:
714 XMLUnknown( XMLDocument* doc );
715 virtual ~XMLUnknown();
716 XMLUnknown( const XMLUnknown& ); // not supported
717 void operator=( const XMLUnknown& ); // not supported
718 };
721 enum {
722 XML_NO_ERROR = 0,
723 XML_SUCCESS = 0,
725 XML_NO_ATTRIBUTE,
726 XML_WRONG_ATTRIBUTE_TYPE,
728 XML_ERROR_FILE_NOT_FOUND,
729 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
730 XML_ERROR_ELEMENT_MISMATCH,
731 XML_ERROR_PARSING_ELEMENT,
732 XML_ERROR_PARSING_ATTRIBUTE,
733 XML_ERROR_IDENTIFYING_TAG,
734 XML_ERROR_PARSING_TEXT,
735 XML_ERROR_PARSING_CDATA,
736 XML_ERROR_PARSING_COMMENT,
737 XML_ERROR_PARSING_DECLARATION,
738 XML_ERROR_PARSING_UNKNOWN,
739 XML_ERROR_EMPTY_DOCUMENT,
740 XML_ERROR_MISMATCHED_ELEMENT,
741 XML_ERROR_PARSING
742 };
745 /** An attribute is a name-value pair. Elements have an arbitrary
746 number of attributes, each with a unique name.
748 @note The attributes are not XMLNodes. You may only query the
749 Next() attribute in a list.
750 */
751 class XMLAttribute
752 {
753 friend class XMLElement;
754 public:
755 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
756 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
757 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
759 /** IntAttribute interprets the attribute as an integer, and returns the value.
760 If the value isn't an integer, 0 will be returned. There is no error checking;
761 use QueryIntAttribute() if you need error checking.
762 */
763 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
764 /// Query as an unsigned integer. See IntAttribute()
765 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
766 /// Query as a boolean. See IntAttribute()
767 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
768 /// Query as a double. See IntAttribute()
769 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
770 /// Query as a float. See IntAttribute()
771 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
773 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
774 in the provided paremeter. The function will return XML_NO_ERROR on success,
775 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
776 */
777 int QueryIntValue( int* value ) const;
778 /// See QueryIntAttribute
779 int QueryUnsignedValue( unsigned int* value ) const;
780 /// See QueryIntAttribute
781 int QueryBoolValue( bool* value ) const;
782 /// See QueryIntAttribute
783 int QueryDoubleValue( double* value ) const;
784 /// See QueryIntAttribute
785 int QueryFloatValue( float* value ) const;
787 /// Set the attribute to a string value.
788 void SetAttribute( const char* value );
789 /// Set the attribute to value.
790 void SetAttribute( int value );
791 /// Set the attribute to value.
792 void SetAttribute( unsigned value );
793 /// Set the attribute to value.
794 void SetAttribute( bool value );
795 /// Set the attribute to value.
796 void SetAttribute( double value );
797 /// Set the attribute to value.
798 void SetAttribute( float value );
800 private:
801 enum { BUF_SIZE = 200 };
803 XMLAttribute() : next( 0 ) {}
804 virtual ~XMLAttribute() {}
805 XMLAttribute( const XMLAttribute& ); // not supported
806 void operator=( const XMLAttribute& ); // not supported
807 void SetName( const char* name );
809 char* ParseDeep( char* p, bool processEntities );
811 mutable StrPair name;
812 mutable StrPair value;
813 XMLAttribute* next;
814 MemPool* memPool;
815 };
818 /** The element is a container class. It has a value, the element name,
819 and can contain other elements, text, comments, and unknowns.
820 Elements also contain an arbitrary number of attributes.
821 */
822 class XMLElement : public XMLNode
823 {
824 friend class XMLBase;
825 friend class XMLDocument;
826 public:
827 /// Get the name of an element (which is the Value() of the node.)
828 const char* Name() const { return Value(); }
829 /// Set the name of the element.
830 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
832 virtual XMLElement* ToElement() { return this; }
833 virtual const XMLElement* ToElement() const { return this; }
834 virtual bool Accept( XMLVisitor* visitor ) const;
836 /** Given an attribute name, Attribute() returns the value
837 for the attribute of that name, or null if none
838 exists. For example:
840 @verbatim
841 const char* value = ele->Attribute( "foo" );
842 @endverbatim
844 The 'value' parameter is normally null. However, if specified,
845 the attribute will only be returned if the 'name' and 'value'
846 match. This allow you to write code:
848 @verbatim
849 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
850 @endverbatim
852 rather than:
853 @verbatim
854 if ( ele->Attribute( "foo" ) ) {
855 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
856 }
857 @endverbatim
858 */
859 const char* Attribute( const char* name, const char* value=0 ) const;
861 /** Given an attribute name, IntAttribute() returns the value
862 of the attribute interpreted as an integer. 0 will be
863 returned if there is an error. For a method with error
864 checking, see QueryIntAttribute()
865 */
866 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
867 /// See IntAttribute()
868 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
869 /// See IntAttribute()
870 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
871 /// See IntAttribute()
872 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
873 /// See IntAttribute()
874 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
876 /** Given an attribute name, QueryIntAttribute() returns
877 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
878 can't be performed, or XML_NO_ATTRIBUTE if the attribute
879 doesn't exist. If successful, the result of the conversion
880 will be written to 'value'. If not successful, nothing will
881 be written to 'value'. This allows you to provide default
882 value:
884 @verbatim
885 int value = 10;
886 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
887 @endverbatim
888 */
889 int QueryIntAttribute( const char* name, int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
890 /// See QueryIntAttribute()
891 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
892 /// See QueryIntAttribute()
893 int QueryBoolAttribute( const char* name, bool* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
894 /// See QueryIntAttribute()
895 int QueryDoubleAttribute( const char* name, double* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
896 /// See QueryIntAttribute()
897 int QueryFloatAttribute( const char* name, float* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
899 /// Sets the named attribute to value.
900 void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
901 /// Sets the named attribute to value.
902 void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
903 /// Sets the named attribute to value.
904 void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
905 /// Sets the named attribute to value.
906 void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
907 /// Sets the named attribute to value.
908 void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
910 /**
911 Delete an attribute.
912 */
913 void DeleteAttribute( const char* name );
915 /// Return the first attribute in the list.
916 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
917 /// Query a specific attribute in the list.
918 const XMLAttribute* FindAttribute( const char* name ) const;
920 /** Convenience function for easy access to the text inside an element. Although easy
921 and concise, GetText() is limited compared to getting the TiXmlText child
922 and accessing it directly.
924 If the first child of 'this' is a TiXmlText, the GetText()
925 returns the character string of the Text node, else null is returned.
927 This is a convenient method for getting the text of simple contained text:
928 @verbatim
929 <foo>This is text</foo>
930 const char* str = fooElement->GetText();
931 @endverbatim
933 'str' will be a pointer to "This is text".
935 Note that this function can be misleading. If the element foo was created from
936 this XML:
937 @verbatim
938 <foo><b>This is text</b></foo>
939 @endverbatim
941 then the value of str would be null. The first child node isn't a text node, it is
942 another element. From this XML:
943 @verbatim
944 <foo>This is <b>text</b></foo>
945 @endverbatim
946 GetText() will return "This is ".
947 */
948 const char* GetText() const;
950 // internal:
951 enum {
952 OPEN, // <foo>
953 CLOSED, // <foo/>
954 CLOSING // </foo>
955 };
956 int ClosingType() const { return closingType; }
957 char* ParseDeep( char* p, StrPair* endTag );
958 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
959 virtual bool ShallowEqual( const XMLNode* compare ) const;
961 private:
962 XMLElement( XMLDocument* doc );
963 virtual ~XMLElement();
964 XMLElement( const XMLElement& ); // not supported
965 void operator=( const XMLElement& ); // not supported
967 XMLAttribute* FindAttribute( const char* name );
968 XMLAttribute* FindOrCreateAttribute( const char* name );
969 //void LinkAttribute( XMLAttribute* attrib );
970 char* ParseAttributes( char* p );
972 int closingType;
973 // The attribute list is ordered; there is no 'lastAttribute'
974 // because the list needs to be scanned for dupes before adding
975 // a new attribute.
976 XMLAttribute* rootAttribute;
977 };
980 /** A Document binds together all the functionality.
981 It can be saved, loaded, and printed to the screen.
982 All Nodes are connected and allocated to a Document.
983 If the Document is deleted, all its Nodes are also deleted.
984 */
985 class XMLDocument : public XMLNode
986 {
987 friend class XMLElement;
988 public:
989 /// constructor
990 XMLDocument( bool processEntities = true );
991 ~XMLDocument();
993 virtual XMLDocument* ToDocument() { return this; }
994 virtual const XMLDocument* ToDocument() const { return this; }
996 /**
997 Parse an XML file from a character string.
998 Returns XML_NO_ERROR (0) on success, or
999 an errorID.
1000 */
1001 int Parse( const char* xml );
1003 /**
1004 Load an XML file from disk.
1005 Returns XML_NO_ERROR (0) on success, or
1006 an errorID.
1007 */
1008 int LoadFile( const char* filename );
1010 /**
1011 Load an XML file from disk. You are responsible
1012 for providing and closing the FILE*.
1014 Returns XML_NO_ERROR (0) on success, or
1015 an errorID.
1016 */
1017 int LoadFile( FILE* );
1019 /**
1020 Save the XML file to disk.
1021 Returns XML_NO_ERROR (0) on success, or
1022 an errorID.
1023 */
1024 int SaveFile( const char* filename );
1026 /**
1027 Save the XML file to disk. You are responsible
1028 for providing and closing the FILE*.
1030 Returns XML_NO_ERROR (0) on success, or
1031 an errorID.
1032 */
1033 int SaveFile( FILE* );
1035 bool ProcessEntities() const { return processEntities; }
1037 /**
1038 Returns true if this document has a leading Byte Order Mark of UTF8.
1039 */
1040 bool HasBOM() const { return writeBOM; }
1041 /** Sets whether to write the BOM when writing the file.
1042 */
1043 void SetBOM( bool useBOM ) { writeBOM = useBOM; }
1045 /** Return the root element of DOM. Equivalent to FirstChildElement().
1046 To get the first node, use FirstChild().
1047 */
1048 XMLElement* RootElement() { return FirstChildElement(); }
1049 const XMLElement* RootElement() const { return FirstChildElement(); }
1051 /** Print the Document. If the Printer is not provided, it will
1052 print to stdout. If you provide Printer, this can print to a file:
1053 @verbatim
1054 XMLPrinter printer( fp );
1055 doc.Print( &printer );
1056 @endverbatim
1058 Or you can use a printer to print to memory:
1059 @verbatim
1060 XMLPrinter printer;
1061 doc->Print( &printer );
1062 // printer.CStr() has a const char* to the XML
1063 @endverbatim
1064 */
1065 void Print( XMLPrinter* streamer=0 );
1066 virtual bool Accept( XMLVisitor* visitor ) const;
1068 /**
1069 Create a new Element associated with
1070 this Document. The memory for the Element
1071 is managed by the Document.
1072 */
1073 XMLElement* NewElement( const char* name );
1074 /**
1075 Create a new Comment associated with
1076 this Document. The memory for the Comment
1077 is managed by the Document.
1078 */
1079 XMLComment* NewComment( const char* comment );
1080 /**
1081 Create a new Text associated with
1082 this Document. The memory for the Text
1083 is managed by the Document.
1084 */
1085 XMLText* NewText( const char* text );
1086 /**
1087 Create a new Declaration associated with
1088 this Document. The memory for the object
1089 is managed by the Document.
1091 If the 'text' param is null, the standard
1092 declaration is used.:
1093 @verbatim
1094 <?xml version="1.0" encoding="UTF-8"?>
1095 @endverbatim
1096 */
1097 XMLDeclaration* NewDeclaration( const char* text=0 );
1098 /**
1099 Create a new Unknown associated with
1100 this Document. The memory for the object
1101 is managed by the Document.
1102 */
1103 XMLUnknown* NewUnknown( const char* text );
1105 /**
1106 Delete a node associated with this document.
1107 It will be unlinked from the DOM.
1108 */
1109 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1111 void SetError( int error, const char* str1, const char* str2 );
1113 /// Return true if there was an error parsing the document.
1114 bool Error() const { return errorID != XML_NO_ERROR; }
1115 /// Return the errorID.
1116 int ErrorID() const { return errorID; }
1117 /// Return a possibly helpful diagnostic location or string.
1118 const char* GetErrorStr1() const { return errorStr1; }
1119 /// Return a possibly helpful secondary diagnostic location or string.
1120 const char* GetErrorStr2() const { return errorStr2; }
1121 /// If there is an error, print it to stdout.
1122 void PrintError() const;
1124 // internal
1125 char* Identify( char* p, XMLNode** node );
1127 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
1128 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
1130 private:
1131 XMLDocument( const XMLDocument& ); // not supported
1132 void operator=( const XMLDocument& ); // not supported
1133 void InitDocument();
1135 bool writeBOM;
1136 bool processEntities;
1137 int errorID;
1138 const char* errorStr1;
1139 const char* errorStr2;
1140 char* charBuffer;
1142 MemPoolT< sizeof(XMLElement) > elementPool;
1143 MemPoolT< sizeof(XMLAttribute) > attributePool;
1144 MemPoolT< sizeof(XMLText) > textPool;
1145 MemPoolT< sizeof(XMLComment) > commentPool;
1146 };
1149 /**
1150 A XMLHandle is a class that wraps a node pointer with null checks; this is
1151 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
1152 DOM structure. It is a separate utility class.
1154 Take an example:
1155 @verbatim
1156 <Document>
1157 <Element attributeA = "valueA">
1158 <Child attributeB = "value1" />
1159 <Child attributeB = "value2" />
1160 </Element>
1161 </Document>
1162 @endverbatim
1164 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1165 easy to write a *lot* of code that looks like:
1167 @verbatim
1168 XMLElement* root = document.FirstChildElement( "Document" );
1169 if ( root )
1171 XMLElement* element = root->FirstChildElement( "Element" );
1172 if ( element )
1174 XMLElement* child = element->FirstChildElement( "Child" );
1175 if ( child )
1177 XMLElement* child2 = child->NextSiblingElement( "Child" );
1178 if ( child2 )
1180 // Finally do something useful.
1181 @endverbatim
1183 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1184 of such code. A XMLHandle checks for null pointers so it is perfectly safe
1185 and correct to use:
1187 @verbatim
1188 XMLHandle docHandle( &document );
1189 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
1190 if ( child2 )
1192 // do something useful
1193 @endverbatim
1195 Which is MUCH more concise and useful.
1197 It is also safe to copy handles - internally they are nothing more than node pointers.
1198 @verbatim
1199 XMLHandle handleCopy = handle;
1200 @endverbatim
1202 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1203 */
1204 class XMLHandle
1206 public:
1207 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1208 XMLHandle( XMLNode* _node ) { node = _node; }
1209 /// Create a handle from a node.
1210 XMLHandle( XMLNode& _node ) { node = &_node; }
1211 /// Copy constructor
1212 XMLHandle( const XMLHandle& ref ) { node = ref.node; }
1213 /// Assignment
1214 XMLHandle operator=( const XMLHandle& ref ) { node = ref.node; return *this; }
1216 /// Get the first child of this handle.
1217 XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); }
1218 /// Get the first child element of this handle.
1219 XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
1220 /// Get the last child of this handle.
1221 XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); }
1222 /// Get the last child element of this handle.
1223 XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
1224 /// Get the previous sibling of this handle.
1225 XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
1226 /// Get the previous sibling element of this handle.
1227 XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1228 /// Get the next sibling of this handle.
1229 XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); }
1230 /// Get the next sibling element of this handle.
1231 XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1233 /// Safe cast to XMLNode. This can return null.
1234 XMLNode* ToNode() { return node; }
1235 /// Safe cast to XMLElement. This can return null.
1236 XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1237 /// Safe cast to XMLText. This can return null.
1238 XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1239 /// Safe cast to XMLUnknown. This can return null.
1240 XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1241 /// Safe cast to XMLDeclaration. This can return null.
1242 XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1244 private:
1245 XMLNode* node;
1246 };
1249 /**
1250 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1251 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1252 */
1253 class XMLConstHandle
1255 public:
1256 XMLConstHandle( const XMLNode* _node ) { node = _node; }
1257 XMLConstHandle( const XMLNode& _node ) { node = &_node; }
1258 XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; }
1260 XMLConstHandle operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; }
1262 const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1263 const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
1264 const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); }
1265 const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
1266 const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1267 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1268 const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1269 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1272 const XMLNode* ToNode() const { return node; }
1273 const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1274 const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1275 const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1276 const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1278 private:
1279 const XMLNode* node;
1280 };
1283 /**
1284 Printing functionality. The XMLPrinter gives you more
1285 options than the XMLDocument::Print() method.
1287 It can:
1288 -# Print to memory.
1289 -# Print to a file you provide.
1290 -# Print XML without a XMLDocument.
1292 Print to Memory
1294 @verbatim
1295 XMLPrinter printer;
1296 doc->Print( &printer );
1297 SomeFunction( printer.CStr() );
1298 @endverbatim
1300 Print to a File
1302 You provide the file pointer.
1303 @verbatim
1304 XMLPrinter printer( fp );
1305 doc.Print( &printer );
1306 @endverbatim
1308 Print without a XMLDocument
1310 When loading, an XML parser is very useful. However, sometimes
1311 when saving, it just gets in the way. The code is often set up
1312 for streaming, and constructing the DOM is just overhead.
1314 The Printer supports the streaming case. The following code
1315 prints out a trivially simple XML file without ever creating
1316 an XML document.
1318 @verbatim
1319 XMLPrinter printer( fp );
1320 printer.OpenElement( "foo" );
1321 printer.PushAttribute( "foo", "bar" );
1322 printer.CloseElement();
1323 @endverbatim
1324 */
1325 class XMLPrinter : public XMLVisitor
1327 public:
1328 /** Construct the printer. If the FILE* is specified,
1329 this will print to the FILE. Else it will print
1330 to memory, and the result is available in CStr()
1331 */
1332 XMLPrinter( FILE* file=0 );
1333 ~XMLPrinter() {}
1335 /** If streaming, write the BOM and declaration. */
1336 void PushHeader( bool writeBOM, bool writeDeclaration );
1337 /** If streaming, start writing an element.
1338 The element must be closed with CloseElement()
1339 */
1340 void OpenElement( const char* name );
1341 /// If streaming, add an attribute to an open element.
1342 void PushAttribute( const char* name, const char* value );
1343 void PushAttribute( const char* name, int value );
1344 void PushAttribute( const char* name, unsigned value );
1345 void PushAttribute( const char* name, bool value );
1346 void PushAttribute( const char* name, double value );
1347 /// If streaming, close the Element.
1348 void CloseElement();
1350 /// Add a text node.
1351 void PushText( const char* text, bool cdata=false );
1352 /// Add a comment.
1353 void PushComment( const char* comment );
1355 void PushDeclaration( const char* value );
1356 void PushUnknown( const char* value );
1358 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1359 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1361 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1362 virtual bool VisitExit( const XMLElement& element );
1364 virtual bool Visit( const XMLText& text );
1365 virtual bool Visit( const XMLComment& comment );
1366 virtual bool Visit( const XMLDeclaration& declaration );
1367 virtual bool Visit( const XMLUnknown& unknown );
1369 /**
1370 If in print to memory mode, return a pointer to
1371 the XML file in memory.
1372 */
1373 const char* CStr() const { return buffer.Mem(); }
1375 private:
1376 void SealElement();
1377 void PrintSpace( int depth );
1378 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1379 void Print( const char* format, ... );
1381 bool elementJustOpened;
1382 bool firstElement;
1383 FILE* fp;
1384 int depth;
1385 int textDepth;
1386 bool processEntities;
1388 enum {
1389 ENTITY_RANGE = 64,
1390 BUF_SIZE = 200
1391 };
1392 bool entityFlag[ENTITY_RANGE];
1393 bool restrictedEntityFlag[ENTITY_RANGE];
1395 DynArray< const char*, 10 > stack;
1396 DynArray< char, 20 > buffer, accumulator;
1397 };
1400 } // tinyxml2
1403 #endif // TINYXML2_INCLUDED