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
24 #ifndef TINYXML2_INCLUDED
25 #define TINYXML2_INCLUDED
27 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
42 TODO: intern strings instead of allocation.
46 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
48 Formatting, Artistic Style:
49 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
52 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
59 # pragma warning(push)
60 # pragma warning(disable: 4251)
64 # ifdef TINYXML2_EXPORT
65 # define TINYXML2_LIB __declspec(dllexport)
66 # elif defined(TINYXML2_IMPORT)
67 # define TINYXML2_LIB __declspec(dllimport)
77 # if defined(_MSC_VER)
78 # // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
79 # define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
80 # elif defined (ANDROID_NDK)
81 # include <android/log.h>
82 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85 # define TIXMLASSERT assert
88 # define TIXMLASSERT( x ) {}
92 /* Versioning, past 1.0.14:
95 static const int TIXML2_MAJOR_VERSION
= 3;
96 static const int TIXML2_MINOR_VERSION
= 0;
97 static const int TIXML2_PATCH_VERSION
= 0;
106 class XMLDeclaration
;
111 A class that wraps strings. Normally stores the start and end
112 pointers into the XML file itself, and will apply normalization
113 and entity translation if actually read. Can also store (and memory
114 manage) a traditional char[]
120 NEEDS_ENTITY_PROCESSING
= 0x01,
121 NEEDS_NEWLINE_NORMALIZATION
= 0x02,
122 NEEDS_WHITESPACE_COLLAPSING
= 0x04,
124 TEXT_ELEMENT
= NEEDS_ENTITY_PROCESSING
| NEEDS_NEWLINE_NORMALIZATION
,
125 TEXT_ELEMENT_LEAVE_ENTITIES
= NEEDS_NEWLINE_NORMALIZATION
,
127 ATTRIBUTE_VALUE
= NEEDS_ENTITY_PROCESSING
| NEEDS_NEWLINE_NORMALIZATION
,
128 ATTRIBUTE_VALUE_LEAVE_ENTITIES
= NEEDS_NEWLINE_NORMALIZATION
,
129 COMMENT
= NEEDS_NEWLINE_NORMALIZATION
132 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
135 void Set( char* start
, char* end
, int flags
) {
139 _flags
= flags
| NEEDS_FLUSH
;
142 const char* GetStr();
145 return _start
== _end
;
148 void SetInternedStr( const char* str
) {
150 _start
= const_cast<char*>(str
);
153 void SetStr( const char* str
, int flags
=0 );
155 char* ParseText( char* in
, const char* endTag
, int strFlags
);
156 char* ParseName( char* in
);
158 void TransferTo( StrPair
* other
);
162 void CollapseWhitespace();
173 StrPair( const StrPair
& other
); // not supported
174 void operator=( StrPair
& other
); // not supported, use TransferTo()
179 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
180 Has a small initial memory pool, so that low or no usage will not
181 cause a call to new/delete
183 template <class T
, int INITIAL_SIZE
>
189 _allocated
= INITIAL_SIZE
;
194 if ( _mem
!= _pool
) {
204 TIXMLASSERT( _size
< INT_MAX
);
205 EnsureCapacity( _size
+1 );
209 T
* PushArr( int count
) {
210 TIXMLASSERT( count
>= 0 );
211 TIXMLASSERT( _size
<= INT_MAX
- count
);
212 EnsureCapacity( _size
+count
);
213 T
* ret
= &_mem
[_size
];
219 TIXMLASSERT( _size
> 0 );
220 return _mem
[--_size
];
223 void PopArr( int count
) {
224 TIXMLASSERT( _size
>= count
);
232 T
& operator[](int i
) {
233 TIXMLASSERT( i
>= 0 && i
< _size
);
237 const T
& operator[](int i
) const {
238 TIXMLASSERT( i
>= 0 && i
< _size
);
242 const T
& PeekTop() const {
243 TIXMLASSERT( _size
> 0 );
244 return _mem
[ _size
- 1];
248 TIXMLASSERT( _size
>= 0 );
252 int Capacity() const {
253 TIXMLASSERT( _allocated
>= INITIAL_SIZE
);
257 const T
* Mem() const {
268 DynArray( const DynArray
& ); // not supported
269 void operator=( const DynArray
& ); // not supported
271 void EnsureCapacity( int cap
) {
272 TIXMLASSERT( cap
> 0 );
273 if ( cap
> _allocated
) {
274 TIXMLASSERT( cap
<= INT_MAX
/ 2 );
275 int newAllocated
= cap
* 2;
276 T
* newMem
= new T
[newAllocated
];
277 memcpy( newMem
, _mem
, sizeof(T
)*_size
); // warning: not using constructors, only works for PODs
278 if ( _mem
!= _pool
) {
282 _allocated
= newAllocated
;
287 T _pool
[INITIAL_SIZE
];
288 int _allocated
; // objects allocated
289 int _size
; // number objects in use
294 Parent virtual class of a pool for fast allocation
295 and deallocation of objects.
301 virtual ~MemPool() {}
303 virtual int ItemSize() const = 0;
304 virtual void* Alloc() = 0;
305 virtual void Free( void* ) = 0;
306 virtual void SetTracked() = 0;
307 virtual void Clear() = 0;
312 Template child class to create pools of the correct type.
315 class MemPoolT
: public MemPool
318 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
324 // Delete the blocks.
325 while( !_blockPtrs
.Empty()) {
326 Block
* b
= _blockPtrs
.Pop();
336 virtual int ItemSize() const {
339 int CurrentAllocs() const {
340 return _currentAllocs
;
343 virtual void* Alloc() {
346 Block
* block
= new Block();
347 _blockPtrs
.Push( block
);
349 for( int i
=0; i
<COUNT
-1; ++i
) {
350 block
->chunk
[i
].next
= &block
->chunk
[i
+1];
352 block
->chunk
[COUNT
-1].next
= 0;
353 _root
= block
->chunk
;
355 void* result
= _root
;
359 if ( _currentAllocs
> _maxAllocs
) {
360 _maxAllocs
= _currentAllocs
;
367 virtual void Free( void* mem
) {
372 Chunk
* chunk
= static_cast<Chunk
*>( mem
);
374 memset( chunk
, 0xfe, sizeof(Chunk
) );
379 void Trace( const char* name
) {
380 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
381 name
, _maxAllocs
, _maxAllocs
*SIZE
/1024, _currentAllocs
, SIZE
, _nAllocs
, _blockPtrs
.Size() );
388 int Untracked() const {
392 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
393 // The test file is large, 170k.
394 // Release: VS2010 gcc(no opt)
401 enum { COUNT
= (4*1024)/SIZE
}; // Some compilers do not accept to use COUNT in private part if COUNT is private
404 MemPoolT( const MemPoolT
& ); // not supported
405 void operator=( const MemPoolT
& ); // not supported
414 DynArray
< Block
*, 10 > _blockPtrs
;
426 Implements the interface to the "Visitor pattern" (see the Accept() method.)
427 If you call the Accept() method, it requires being passed a XMLVisitor
428 class to handle callbacks. For nodes that contain other nodes (Document, Element)
429 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
430 are simply called with Visit().
432 If you return 'true' from a Visit method, recursive parsing will continue. If you return
433 false, <b>no children of this node or its siblings</b> will be visited.
435 All flavors of Visit methods have a default implementation that returns 'true' (continue
436 visiting). You need to only override methods that are interesting to you.
438 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
440 You should never change the document from a callback.
442 @sa XMLNode::Accept()
444 class TINYXML2_LIB XMLVisitor
447 virtual ~XMLVisitor() {}
449 /// Visit a document.
450 virtual bool VisitEnter( const XMLDocument
& /*doc*/ ) {
453 /// Visit a document.
454 virtual bool VisitExit( const XMLDocument
& /*doc*/ ) {
458 /// Visit an element.
459 virtual bool VisitEnter( const XMLElement
& /*element*/, const XMLAttribute
* /*firstAttribute*/ ) {
462 /// Visit an element.
463 virtual bool VisitExit( const XMLElement
& /*element*/ ) {
467 /// Visit a declaration.
468 virtual bool Visit( const XMLDeclaration
& /*declaration*/ ) {
471 /// Visit a text node.
472 virtual bool Visit( const XMLText
& /*text*/ ) {
475 /// Visit a comment node.
476 virtual bool Visit( const XMLComment
& /*comment*/ ) {
479 /// Visit an unknown node.
480 virtual bool Visit( const XMLUnknown
& /*unknown*/ ) {
485 // WARNING: must match XMLDocument::_errorNames[]
490 XML_WRONG_ATTRIBUTE_TYPE
,
491 XML_ERROR_FILE_NOT_FOUND
,
492 XML_ERROR_FILE_COULD_NOT_BE_OPENED
,
493 XML_ERROR_FILE_READ_ERROR
,
494 XML_ERROR_ELEMENT_MISMATCH
,
495 XML_ERROR_PARSING_ELEMENT
,
496 XML_ERROR_PARSING_ATTRIBUTE
,
497 XML_ERROR_IDENTIFYING_TAG
,
498 XML_ERROR_PARSING_TEXT
,
499 XML_ERROR_PARSING_CDATA
,
500 XML_ERROR_PARSING_COMMENT
,
501 XML_ERROR_PARSING_DECLARATION
,
502 XML_ERROR_PARSING_UNKNOWN
,
503 XML_ERROR_EMPTY_DOCUMENT
,
504 XML_ERROR_MISMATCHED_ELEMENT
,
506 XML_CAN_NOT_CONVERT_TEXT
,
514 Utility functionality.
519 static const char* SkipWhiteSpace( const char* p
) {
521 while( IsWhiteSpace(*p
) ) {
527 static char* SkipWhiteSpace( char* p
) {
528 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p
) ) );
531 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
532 // correct, but simple, and usually works.
533 static bool IsWhiteSpace( char p
) {
534 return !IsUTF8Continuation(p
) && isspace( static_cast<unsigned char>(p
) );
537 inline static bool IsNameStartChar( unsigned char ch
) {
539 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
542 if ( isalpha( ch
) ) {
545 return ch
== ':' || ch
== '_';
548 inline static bool IsNameChar( unsigned char ch
) {
549 return IsNameStartChar( ch
)
555 inline static bool StringEqual( const char* p
, const char* q
, int nChar
=INT_MAX
) {
559 return strncmp( p
, q
, nChar
) == 0;
562 inline static bool IsUTF8Continuation( char p
) {
563 return ( p
& 0x80 ) != 0;
566 static const char* ReadBOM( const char* p
, bool* hasBOM
);
567 // p is the starting location,
568 // the UTF-8 value of the entity will be placed in value, and length filled in.
569 static const char* GetCharacterRef( const char* p
, char* value
, int* length
);
570 static void ConvertUTF32ToUTF8( unsigned long input
, char* output
, int* length
);
572 // converts primitive types to strings
573 static void ToStr( int v
, char* buffer
, int bufferSize
);
574 static void ToStr( unsigned v
, char* buffer
, int bufferSize
);
575 static void ToStr( bool v
, char* buffer
, int bufferSize
);
576 static void ToStr( float v
, char* buffer
, int bufferSize
);
577 static void ToStr( double v
, char* buffer
, int bufferSize
);
579 // converts strings to primitive types
580 static bool ToInt( const char* str
, int* value
);
581 static bool ToUnsigned( const char* str
, unsigned* value
);
582 static bool ToBool( const char* str
, bool* value
);
583 static bool ToFloat( const char* str
, float* value
);
584 static bool ToDouble( const char* str
, double* value
);
588 /** XMLNode is a base class for every object that is in the
589 XML Document Object Model (DOM), except XMLAttributes.
590 Nodes have siblings, a parent, and children which can
591 be navigated. A node is always in a XMLDocument.
592 The type of a XMLNode can be queried, and it can
593 be cast to its more defined type.
595 A XMLDocument allocates memory for all its Nodes.
596 When the XMLDocument gets deleted, all its Nodes
597 will also be deleted.
600 A Document can contain: Element (container or leaf)
605 An Element can contain: Element (container or leaf)
607 Attributes (not on tree)
613 class TINYXML2_LIB XMLNode
615 friend class XMLDocument
;
616 friend class XMLElement
;
619 /// Get the XMLDocument that owns this XMLNode.
620 const XMLDocument
* GetDocument() const {
621 TIXMLASSERT( _document
);
624 /// Get the XMLDocument that owns this XMLNode.
625 XMLDocument
* GetDocument() {
626 TIXMLASSERT( _document
);
630 /// Safely cast to an Element, or null.
631 virtual XMLElement
* ToElement() {
634 /// Safely cast to Text, or null.
635 virtual XMLText
* ToText() {
638 /// Safely cast to a Comment, or null.
639 virtual XMLComment
* ToComment() {
642 /// Safely cast to a Document, or null.
643 virtual XMLDocument
* ToDocument() {
646 /// Safely cast to a Declaration, or null.
647 virtual XMLDeclaration
* ToDeclaration() {
650 /// Safely cast to an Unknown, or null.
651 virtual XMLUnknown
* ToUnknown() {
655 virtual const XMLElement
* ToElement() const {
658 virtual const XMLText
* ToText() const {
661 virtual const XMLComment
* ToComment() const {
664 virtual const XMLDocument
* ToDocument() const {
667 virtual const XMLDeclaration
* ToDeclaration() const {
670 virtual const XMLUnknown
* ToUnknown() const {
674 /** The meaning of 'value' changes for the specific type.
676 Document: empty (NULL is returned, not an empty string)
677 Element: name of the element
678 Comment: the comment text
679 Unknown: the tag contents
680 Text: the text string
683 const char* Value() const;
685 /** Set the Value of an XML node.
688 void SetValue( const char* val
, bool staticMem
=false );
690 /// Get the parent of this node on the DOM.
691 const XMLNode
* Parent() const {
699 /// Returns true if this node has no children.
700 bool NoChildren() const {
704 /// Get the first child node, or null if none exists.
705 const XMLNode
* FirstChild() const {
709 XMLNode
* FirstChild() {
713 /** Get the first child element, or optionally the first child
714 element with the specified name.
716 const XMLElement
* FirstChildElement( const char* name
= 0 ) const;
718 XMLElement
* FirstChildElement( const char* name
= 0 ) {
719 return const_cast<XMLElement
*>(const_cast<const XMLNode
*>(this)->FirstChildElement( name
));
722 /// Get the last child node, or null if none exists.
723 const XMLNode
* LastChild() const {
727 XMLNode
* LastChild() {
731 /** Get the last child element or optionally the last child
732 element with the specified name.
734 const XMLElement
* LastChildElement( const char* name
= 0 ) const;
736 XMLElement
* LastChildElement( const char* name
= 0 ) {
737 return const_cast<XMLElement
*>(const_cast<const XMLNode
*>(this)->LastChildElement(name
) );
740 /// Get the previous (left) sibling node of this node.
741 const XMLNode
* PreviousSibling() const {
745 XMLNode
* PreviousSibling() {
749 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
750 const XMLElement
* PreviousSiblingElement( const char* name
= 0 ) const ;
752 XMLElement
* PreviousSiblingElement( const char* name
= 0 ) {
753 return const_cast<XMLElement
*>(const_cast<const XMLNode
*>(this)->PreviousSiblingElement( name
) );
756 /// Get the next (right) sibling node of this node.
757 const XMLNode
* NextSibling() const {
761 XMLNode
* NextSibling() {
765 /// Get the next (right) sibling element of this node, with an optionally supplied name.
766 const XMLElement
* NextSiblingElement( const char* name
= 0 ) const;
768 XMLElement
* NextSiblingElement( const char* name
= 0 ) {
769 return const_cast<XMLElement
*>(const_cast<const XMLNode
*>(this)->NextSiblingElement( name
) );
773 Add a child node as the last (right) child.
774 If the child node is already part of the document,
775 it is moved from its old location to the new location.
776 Returns the addThis argument or 0 if the node does not
777 belong to the same document.
779 XMLNode
* InsertEndChild( XMLNode
* addThis
);
781 XMLNode
* LinkEndChild( XMLNode
* addThis
) {
782 return InsertEndChild( addThis
);
785 Add a child node as the first (left) child.
786 If the child node is already part of the document,
787 it is moved from its old location to the new location.
788 Returns the addThis argument or 0 if the node does not
789 belong to the same document.
791 XMLNode
* InsertFirstChild( XMLNode
* addThis
);
793 Add a node after the specified child node.
794 If the child node is already part of the document,
795 it is moved from its old location to the new location.
796 Returns the addThis argument or 0 if the afterThis node
797 is not a child of this node, or if the node does not
798 belong to the same document.
800 XMLNode
* InsertAfterChild( XMLNode
* afterThis
, XMLNode
* addThis
);
803 Delete all the children of this node.
805 void DeleteChildren();
808 Delete a child of this node.
810 void DeleteChild( XMLNode
* node
);
813 Make a copy of this node, but not its children.
814 You may pass in a Document pointer that will be
815 the owner of the new Node. If the 'document' is
816 null, then the node returned will be allocated
817 from the current Document. (this->GetDocument())
819 Note: if called on a XMLDocument, this will return null.
821 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const = 0;
824 Test if 2 nodes are the same, but don't test children.
825 The 2 nodes do not need to be in the same Document.
827 Note: if called on a XMLDocument, this will return false.
829 virtual bool ShallowEqual( const XMLNode
* compare
) const = 0;
831 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
832 XML tree will be conditionally visited and the host will be called back
833 via the XMLVisitor interface.
835 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
836 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
837 interface versus any other.)
839 The interface has been based on ideas from:
841 - http://www.saxproject.org/
842 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
844 Which are both good references for "visiting".
846 An example of using Accept():
849 tinyxmlDoc.Accept( &printer );
850 const char* xmlcstr = printer.CStr();
853 virtual bool Accept( XMLVisitor
* visitor
) const = 0;
856 XMLNode( XMLDocument
* );
859 virtual char* ParseDeep( char*, StrPair
* );
861 XMLDocument
* _document
;
863 mutable StrPair _value
;
865 XMLNode
* _firstChild
;
873 void Unlink( XMLNode
* child
);
874 static void DeleteNode( XMLNode
* node
);
875 void InsertChildPreamble( XMLNode
* insertThis
) const;
877 XMLNode( const XMLNode
& ); // not supported
878 XMLNode
& operator=( const XMLNode
& ); // not supported
884 Note that a text node can have child element nodes, for example:
886 <root>This is <b>bold</b></root>
889 A text node can have 2 ways to output the next. "normal" output
890 and CDATA. It will default to the mode it was parsed from the XML file and
891 you generally want to leave it alone, but you can change the output mode with
892 SetCData() and query it with CData().
894 class TINYXML2_LIB XMLText
: public XMLNode
896 friend class XMLBase
;
897 friend class XMLDocument
;
899 virtual bool Accept( XMLVisitor
* visitor
) const;
901 virtual XMLText
* ToText() {
904 virtual const XMLText
* ToText() const {
908 /// Declare whether this should be CDATA or standard text.
909 void SetCData( bool isCData
) {
912 /// Returns true if this is a CDATA text element.
917 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const;
918 virtual bool ShallowEqual( const XMLNode
* compare
) const;
921 XMLText( XMLDocument
* doc
) : XMLNode( doc
), _isCData( false ) {}
922 virtual ~XMLText() {}
924 char* ParseDeep( char*, StrPair
* endTag
);
929 XMLText( const XMLText
& ); // not supported
930 XMLText
& operator=( const XMLText
& ); // not supported
934 /** An XML Comment. */
935 class TINYXML2_LIB XMLComment
: public XMLNode
937 friend class XMLDocument
;
939 virtual XMLComment
* ToComment() {
942 virtual const XMLComment
* ToComment() const {
946 virtual bool Accept( XMLVisitor
* visitor
) const;
948 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const;
949 virtual bool ShallowEqual( const XMLNode
* compare
) const;
952 XMLComment( XMLDocument
* doc
);
953 virtual ~XMLComment();
955 char* ParseDeep( char*, StrPair
* endTag
);
958 XMLComment( const XMLComment
& ); // not supported
959 XMLComment
& operator=( const XMLComment
& ); // not supported
963 /** In correct XML the declaration is the first entry in the file.
965 <?xml version="1.0" standalone="yes"?>
968 TinyXML-2 will happily read or write files without a declaration,
971 The text of the declaration isn't interpreted. It is parsed
972 and written as a string.
974 class TINYXML2_LIB XMLDeclaration
: public XMLNode
976 friend class XMLDocument
;
978 virtual XMLDeclaration
* ToDeclaration() {
981 virtual const XMLDeclaration
* ToDeclaration() const {
985 virtual bool Accept( XMLVisitor
* visitor
) const;
987 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const;
988 virtual bool ShallowEqual( const XMLNode
* compare
) const;
991 XMLDeclaration( XMLDocument
* doc
);
992 virtual ~XMLDeclaration();
994 char* ParseDeep( char*, StrPair
* endTag
);
997 XMLDeclaration( const XMLDeclaration
& ); // not supported
998 XMLDeclaration
& operator=( const XMLDeclaration
& ); // not supported
1002 /** Any tag that TinyXML-2 doesn't recognize is saved as an
1003 unknown. It is a tag of text, but should not be modified.
1004 It will be written back to the XML, unchanged, when the file
1007 DTD tags get thrown into XMLUnknowns.
1009 class TINYXML2_LIB XMLUnknown
: public XMLNode
1011 friend class XMLDocument
;
1013 virtual XMLUnknown
* ToUnknown() {
1016 virtual const XMLUnknown
* ToUnknown() const {
1020 virtual bool Accept( XMLVisitor
* visitor
) const;
1022 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const;
1023 virtual bool ShallowEqual( const XMLNode
* compare
) const;
1026 XMLUnknown( XMLDocument
* doc
);
1027 virtual ~XMLUnknown();
1029 char* ParseDeep( char*, StrPair
* endTag
);
1032 XMLUnknown( const XMLUnknown
& ); // not supported
1033 XMLUnknown
& operator=( const XMLUnknown
& ); // not supported
1038 /** An attribute is a name-value pair. Elements have an arbitrary
1039 number of attributes, each with a unique name.
1041 @note The attributes are not XMLNodes. You may only query the
1042 Next() attribute in a list.
1044 class TINYXML2_LIB XMLAttribute
1046 friend class XMLElement
;
1048 /// The name of the attribute.
1049 const char* Name() const;
1051 /// The value of the attribute.
1052 const char* Value() const;
1054 /// The next attribute in the list.
1055 const XMLAttribute
* Next() const {
1059 /** IntValue interprets the attribute as an integer, and returns the value.
1060 If the value isn't an integer, 0 will be returned. There is no error checking;
1061 use QueryIntValue() if you need error checking.
1063 int IntValue() const {
1065 QueryIntValue( &i
);
1068 /// Query as an unsigned integer. See IntValue()
1069 unsigned UnsignedValue() const {
1071 QueryUnsignedValue( &i
);
1074 /// Query as a boolean. See IntValue()
1075 bool BoolValue() const {
1077 QueryBoolValue( &b
);
1080 /// Query as a double. See IntValue()
1081 double DoubleValue() const {
1083 QueryDoubleValue( &d
);
1086 /// Query as a float. See IntValue()
1087 float FloatValue() const {
1089 QueryFloatValue( &f
);
1093 /** QueryIntValue interprets the attribute as an integer, and returns the value
1094 in the provided parameter. The function will return XML_NO_ERROR on success,
1095 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1097 XMLError
QueryIntValue( int* value
) const;
1098 /// See QueryIntValue
1099 XMLError
QueryUnsignedValue( unsigned int* value
) const;
1100 /// See QueryIntValue
1101 XMLError
QueryBoolValue( bool* value
) const;
1102 /// See QueryIntValue
1103 XMLError
QueryDoubleValue( double* value
) const;
1104 /// See QueryIntValue
1105 XMLError
QueryFloatValue( float* value
) const;
1107 /// Set the attribute to a string value.
1108 void SetAttribute( const char* value
);
1109 /// Set the attribute to value.
1110 void SetAttribute( int value
);
1111 /// Set the attribute to value.
1112 void SetAttribute( unsigned value
);
1113 /// Set the attribute to value.
1114 void SetAttribute( bool value
);
1115 /// Set the attribute to value.
1116 void SetAttribute( double value
);
1117 /// Set the attribute to value.
1118 void SetAttribute( float value
);
1121 enum { BUF_SIZE
= 200 };
1123 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
1124 virtual ~XMLAttribute() {}
1126 XMLAttribute( const XMLAttribute
& ); // not supported
1127 void operator=( const XMLAttribute
& ); // not supported
1128 void SetName( const char* name
);
1130 char* ParseDeep( char* p
, bool processEntities
);
1132 mutable StrPair _name
;
1133 mutable StrPair _value
;
1134 XMLAttribute
* _next
;
1139 /** The element is a container class. It has a value, the element name,
1140 and can contain other elements, text, comments, and unknowns.
1141 Elements also contain an arbitrary number of attributes.
1143 class TINYXML2_LIB XMLElement
: public XMLNode
1145 friend class XMLBase
;
1146 friend class XMLDocument
;
1148 /// Get the name of an element (which is the Value() of the node.)
1149 const char* Name() const {
1152 /// Set the name of the element.
1153 void SetName( const char* str
, bool staticMem
=false ) {
1154 SetValue( str
, staticMem
);
1157 virtual XMLElement
* ToElement() {
1160 virtual const XMLElement
* ToElement() const {
1163 virtual bool Accept( XMLVisitor
* visitor
) const;
1165 /** Given an attribute name, Attribute() returns the value
1166 for the attribute of that name, or null if none
1167 exists. For example:
1170 const char* value = ele->Attribute( "foo" );
1173 The 'value' parameter is normally null. However, if specified,
1174 the attribute will only be returned if the 'name' and 'value'
1175 match. This allow you to write code:
1178 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1183 if ( ele->Attribute( "foo" ) ) {
1184 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1188 const char* Attribute( const char* name
, const char* value
=0 ) const;
1190 /** Given an attribute name, IntAttribute() returns the value
1191 of the attribute interpreted as an integer. 0 will be
1192 returned if there is an error. For a method with error
1193 checking, see QueryIntAttribute()
1195 int IntAttribute( const char* name
) const {
1197 QueryIntAttribute( name
, &i
);
1200 /// See IntAttribute()
1201 unsigned UnsignedAttribute( const char* name
) const {
1203 QueryUnsignedAttribute( name
, &i
);
1206 /// See IntAttribute()
1207 bool BoolAttribute( const char* name
) const {
1209 QueryBoolAttribute( name
, &b
);
1212 /// See IntAttribute()
1213 double DoubleAttribute( const char* name
) const {
1215 QueryDoubleAttribute( name
, &d
);
1218 /// See IntAttribute()
1219 float FloatAttribute( const char* name
) const {
1221 QueryFloatAttribute( name
, &f
);
1225 /** Given an attribute name, QueryIntAttribute() returns
1226 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1227 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1228 doesn't exist. If successful, the result of the conversion
1229 will be written to 'value'. If not successful, nothing will
1230 be written to 'value'. This allows you to provide default
1235 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1238 XMLError
QueryIntAttribute( const char* name
, int* value
) const {
1239 const XMLAttribute
* a
= FindAttribute( name
);
1241 return XML_NO_ATTRIBUTE
;
1243 return a
->QueryIntValue( value
);
1245 /// See QueryIntAttribute()
1246 XMLError
QueryUnsignedAttribute( const char* name
, unsigned int* value
) const {
1247 const XMLAttribute
* a
= FindAttribute( name
);
1249 return XML_NO_ATTRIBUTE
;
1251 return a
->QueryUnsignedValue( value
);
1253 /// See QueryIntAttribute()
1254 XMLError
QueryBoolAttribute( const char* name
, bool* value
) const {
1255 const XMLAttribute
* a
= FindAttribute( name
);
1257 return XML_NO_ATTRIBUTE
;
1259 return a
->QueryBoolValue( value
);
1261 /// See QueryIntAttribute()
1262 XMLError
QueryDoubleAttribute( const char* name
, double* value
) const {
1263 const XMLAttribute
* a
= FindAttribute( name
);
1265 return XML_NO_ATTRIBUTE
;
1267 return a
->QueryDoubleValue( value
);
1269 /// See QueryIntAttribute()
1270 XMLError
QueryFloatAttribute( const char* name
, float* value
) const {
1271 const XMLAttribute
* a
= FindAttribute( name
);
1273 return XML_NO_ATTRIBUTE
;
1275 return a
->QueryFloatValue( value
);
1279 /** Given an attribute name, QueryAttribute() returns
1280 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1281 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1282 doesn't exist. It is overloaded for the primitive types,
1283 and is a generally more convenient replacement of
1284 QueryIntAttribute() and related functions.
1286 If successful, the result of the conversion
1287 will be written to 'value'. If not successful, nothing will
1288 be written to 'value'. This allows you to provide default
1293 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1296 int QueryAttribute( const char* name
, int* value
) const {
1297 return QueryIntAttribute( name
, value
);
1300 int QueryAttribute( const char* name
, unsigned int* value
) const {
1301 return QueryUnsignedAttribute( name
, value
);
1304 int QueryAttribute( const char* name
, bool* value
) const {
1305 return QueryBoolAttribute( name
, value
);
1308 int QueryAttribute( const char* name
, double* value
) const {
1309 return QueryDoubleAttribute( name
, value
);
1312 int QueryAttribute( const char* name
, float* value
) const {
1313 return QueryFloatAttribute( name
, value
);
1316 /// Sets the named attribute to value.
1317 void SetAttribute( const char* name
, const char* value
) {
1318 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1319 a
->SetAttribute( value
);
1321 /// Sets the named attribute to value.
1322 void SetAttribute( const char* name
, int value
) {
1323 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1324 a
->SetAttribute( value
);
1326 /// Sets the named attribute to value.
1327 void SetAttribute( const char* name
, unsigned value
) {
1328 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1329 a
->SetAttribute( value
);
1331 /// Sets the named attribute to value.
1332 void SetAttribute( const char* name
, bool value
) {
1333 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1334 a
->SetAttribute( value
);
1336 /// Sets the named attribute to value.
1337 void SetAttribute( const char* name
, double value
) {
1338 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1339 a
->SetAttribute( value
);
1341 /// Sets the named attribute to value.
1342 void SetAttribute( const char* name
, float value
) {
1343 XMLAttribute
* a
= FindOrCreateAttribute( name
);
1344 a
->SetAttribute( value
);
1348 Delete an attribute.
1350 void DeleteAttribute( const char* name
);
1352 /// Return the first attribute in the list.
1353 const XMLAttribute
* FirstAttribute() const {
1354 return _rootAttribute
;
1356 /// Query a specific attribute in the list.
1357 const XMLAttribute
* FindAttribute( const char* name
) const;
1359 /** Convenience function for easy access to the text inside an element. Although easy
1360 and concise, GetText() is limited compared to getting the XMLText child
1361 and accessing it directly.
1363 If the first child of 'this' is a XMLText, the GetText()
1364 returns the character string of the Text node, else null is returned.
1366 This is a convenient method for getting the text of simple contained text:
1368 <foo>This is text</foo>
1369 const char* str = fooElement->GetText();
1372 'str' will be a pointer to "This is text".
1374 Note that this function can be misleading. If the element foo was created from
1377 <foo><b>This is text</b></foo>
1380 then the value of str would be null. The first child node isn't a text node, it is
1381 another element. From this XML:
1383 <foo>This is <b>text</b></foo>
1385 GetText() will return "This is ".
1387 const char* GetText() const;
1389 /** Convenience function for easy access to the text inside an element. Although easy
1390 and concise, SetText() is limited compared to creating an XMLText child
1391 and mutating it directly.
1393 If the first child of 'this' is a XMLText, SetText() sets its value to
1394 the given string, otherwise it will create a first child that is an XMLText.
1396 This is a convenient method for setting the text of simple contained text:
1398 <foo>This is text</foo>
1399 fooElement->SetText( "Hullaballoo!" );
1400 <foo>Hullaballoo!</foo>
1403 Note that this function can be misleading. If the element foo was created from
1406 <foo><b>This is text</b></foo>
1409 then it will not change "This is text", but rather prefix it with a text element:
1411 <foo>Hullaballoo!<b>This is text</b></foo>
1418 SetText() will generate
1420 <foo>Hullaballoo!</foo>
1423 void SetText( const char* inText
);
1424 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1425 void SetText( int value
);
1426 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1427 void SetText( unsigned value
);
1428 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1429 void SetText( bool value
);
1430 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1431 void SetText( double value
);
1432 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1433 void SetText( float value
);
1436 Convenience method to query the value of a child text node. This is probably best
1437 shown by example. Given you have a document is this form:
1445 The QueryIntText() and similar functions provide a safe and easier way to get to the
1450 float y = 0; // types of x and y are contrived for example
1451 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1452 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1453 xElement->QueryIntText( &x );
1454 yElement->QueryFloatText( &y );
1457 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1458 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1461 XMLError
QueryIntText( int* ival
) const;
1462 /// See QueryIntText()
1463 XMLError
QueryUnsignedText( unsigned* uval
) const;
1464 /// See QueryIntText()
1465 XMLError
QueryBoolText( bool* bval
) const;
1466 /// See QueryIntText()
1467 XMLError
QueryDoubleText( double* dval
) const;
1468 /// See QueryIntText()
1469 XMLError
QueryFloatText( float* fval
) const;
1477 int ClosingType() const {
1478 return _closingType
;
1480 virtual XMLNode
* ShallowClone( XMLDocument
* document
) const;
1481 virtual bool ShallowEqual( const XMLNode
* compare
) const;
1484 char* ParseDeep( char* p
, StrPair
* endTag
);
1487 XMLElement( XMLDocument
* doc
);
1488 virtual ~XMLElement();
1489 XMLElement( const XMLElement
& ); // not supported
1490 void operator=( const XMLElement
& ); // not supported
1492 XMLAttribute
* FindAttribute( const char* name
) {
1493 return const_cast<XMLAttribute
*>(const_cast<const XMLElement
*>(this)->FindAttribute( name
));
1495 XMLAttribute
* FindOrCreateAttribute( const char* name
);
1496 //void LinkAttribute( XMLAttribute* attrib );
1497 char* ParseAttributes( char* p
);
1498 static void DeleteAttribute( XMLAttribute
* attribute
);
1500 enum { BUF_SIZE
= 200 };
1502 // The attribute list is ordered; there is no 'lastAttribute'
1503 // because the list needs to be scanned for dupes before adding
1505 XMLAttribute
* _rootAttribute
;
1510 PRESERVE_WHITESPACE
,
1515 /** A Document binds together all the functionality.
1516 It can be saved, loaded, and printed to the screen.
1517 All Nodes are connected and allocated to a Document.
1518 If the Document is deleted, all its Nodes are also deleted.
1520 class TINYXML2_LIB XMLDocument
: public XMLNode
1522 friend class XMLElement
;
1525 XMLDocument( bool processEntities
= true, Whitespace
= PRESERVE_WHITESPACE
);
1528 virtual XMLDocument
* ToDocument() {
1529 TIXMLASSERT( this == _document
);
1532 virtual const XMLDocument
* ToDocument() const {
1533 TIXMLASSERT( this == _document
);
1538 Parse an XML file from a character string.
1539 Returns XML_NO_ERROR (0) on success, or
1542 You may optionally pass in the 'nBytes', which is
1543 the number of bytes which will be parsed. If not
1544 specified, TinyXML-2 will assume 'xml' points to a
1545 null terminated string.
1547 XMLError
Parse( const char* xml
, size_t nBytes
=(size_t)(-1) );
1550 Load an XML file from disk.
1551 Returns XML_NO_ERROR (0) on success, or
1554 XMLError
LoadFile( const char* filename
);
1557 Load an XML file from disk. You are responsible
1558 for providing and closing the FILE*.
1560 NOTE: The file should be opened as binary ("rb")
1561 not text in order for TinyXML-2 to correctly
1562 do newline normalization.
1564 Returns XML_NO_ERROR (0) on success, or
1567 XMLError
LoadFile( FILE* );
1570 Save the XML file to disk.
1571 Returns XML_NO_ERROR (0) on success, or
1574 XMLError
SaveFile( const char* filename
, bool compact
= false );
1577 Save the XML file to disk. You are responsible
1578 for providing and closing the FILE*.
1580 Returns XML_NO_ERROR (0) on success, or
1583 XMLError
SaveFile( FILE* fp
, bool compact
= false );
1585 bool ProcessEntities() const {
1586 return _processEntities
;
1588 Whitespace
WhitespaceMode() const {
1593 Returns true if this document has a leading Byte Order Mark of UTF8.
1595 bool HasBOM() const {
1598 /** Sets whether to write the BOM when writing the file.
1600 void SetBOM( bool useBOM
) {
1604 /** Return the root element of DOM. Equivalent to FirstChildElement().
1605 To get the first node, use FirstChild().
1607 XMLElement
* RootElement() {
1608 return FirstChildElement();
1610 const XMLElement
* RootElement() const {
1611 return FirstChildElement();
1614 /** Print the Document. If the Printer is not provided, it will
1615 print to stdout. If you provide Printer, this can print to a file:
1617 XMLPrinter printer( fp );
1618 doc.Print( &printer );
1621 Or you can use a printer to print to memory:
1624 doc.Print( &printer );
1625 // printer.CStr() has a const char* to the XML
1628 void Print( XMLPrinter
* streamer
=0 ) const;
1629 virtual bool Accept( XMLVisitor
* visitor
) const;
1632 Create a new Element associated with
1633 this Document. The memory for the Element
1634 is managed by the Document.
1636 XMLElement
* NewElement( const char* name
);
1638 Create a new Comment associated with
1639 this Document. The memory for the Comment
1640 is managed by the Document.
1642 XMLComment
* NewComment( const char* comment
);
1644 Create a new Text associated with
1645 this Document. The memory for the Text
1646 is managed by the Document.
1648 XMLText
* NewText( const char* text
);
1650 Create a new Declaration associated with
1651 this Document. The memory for the object
1652 is managed by the Document.
1654 If the 'text' param is null, the standard
1655 declaration is used.:
1657 <?xml version="1.0" encoding="UTF-8"?>
1660 XMLDeclaration
* NewDeclaration( const char* text
=0 );
1662 Create a new Unknown associated with
1663 this Document. The memory for the object
1664 is managed by the Document.
1666 XMLUnknown
* NewUnknown( const char* text
);
1669 Delete a node associated with this document.
1670 It will be unlinked from the DOM.
1672 void DeleteNode( XMLNode
* node
);
1674 void SetError( XMLError error
, const char* str1
, const char* str2
);
1676 /// Return true if there was an error parsing the document.
1677 bool Error() const {
1678 return _errorID
!= XML_NO_ERROR
;
1680 /// Return the errorID.
1681 XMLError
ErrorID() const {
1684 const char* ErrorName() const;
1686 /// Return a possibly helpful diagnostic location or string.
1687 const char* GetErrorStr1() const {
1690 /// Return a possibly helpful secondary diagnostic location or string.
1691 const char* GetErrorStr2() const {
1694 /// If there is an error, print it to stdout.
1695 void PrintError() const;
1697 /// Clear the document, resetting it to the initial state.
1701 char* Identify( char* p
, XMLNode
** node
);
1703 virtual XMLNode
* ShallowClone( XMLDocument
* /*document*/ ) const {
1706 virtual bool ShallowEqual( const XMLNode
* /*compare*/ ) const {
1711 XMLDocument( const XMLDocument
& ); // not supported
1712 void operator=( const XMLDocument
& ); // not supported
1715 bool _processEntities
;
1717 Whitespace _whitespace
;
1718 const char* _errorStr1
;
1719 const char* _errorStr2
;
1722 MemPoolT
< sizeof(XMLElement
) > _elementPool
;
1723 MemPoolT
< sizeof(XMLAttribute
) > _attributePool
;
1724 MemPoolT
< sizeof(XMLText
) > _textPool
;
1725 MemPoolT
< sizeof(XMLComment
) > _commentPool
;
1727 static const char* _errorNames
[XML_ERROR_COUNT
];
1734 A XMLHandle is a class that wraps a node pointer with null checks; this is
1735 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
1736 DOM structure. It is a separate utility class.
1741 <Element attributeA = "valueA">
1742 <Child attributeB = "value1" />
1743 <Child attributeB = "value2" />
1748 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1749 easy to write a *lot* of code that looks like:
1752 XMLElement* root = document.FirstChildElement( "Document" );
1755 XMLElement* element = root->FirstChildElement( "Element" );
1758 XMLElement* child = element->FirstChildElement( "Child" );
1761 XMLElement* child2 = child->NextSiblingElement( "Child" );
1764 // Finally do something useful.
1767 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1768 of such code. A XMLHandle checks for null pointers so it is perfectly safe
1772 XMLHandle docHandle( &document );
1773 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
1776 // do something useful
1779 Which is MUCH more concise and useful.
1781 It is also safe to copy handles - internally they are nothing more than node pointers.
1783 XMLHandle handleCopy = handle;
1786 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1788 class TINYXML2_LIB XMLHandle
1791 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1792 XMLHandle( XMLNode
* node
) {
1795 /// Create a handle from a node.
1796 XMLHandle( XMLNode
& node
) {
1799 /// Copy constructor
1800 XMLHandle( const XMLHandle
& ref
) {
1804 XMLHandle
& operator=( const XMLHandle
& ref
) {
1809 /// Get the first child of this handle.
1810 XMLHandle
FirstChild() {
1811 return XMLHandle( _node
? _node
->FirstChild() : 0 );
1813 /// Get the first child element of this handle.
1814 XMLHandle
FirstChildElement( const char* name
= 0 ) {
1815 return XMLHandle( _node
? _node
->FirstChildElement( name
) : 0 );
1817 /// Get the last child of this handle.
1818 XMLHandle
LastChild() {
1819 return XMLHandle( _node
? _node
->LastChild() : 0 );
1821 /// Get the last child element of this handle.
1822 XMLHandle
LastChildElement( const char* name
= 0 ) {
1823 return XMLHandle( _node
? _node
->LastChildElement( name
) : 0 );
1825 /// Get the previous sibling of this handle.
1826 XMLHandle
PreviousSibling() {
1827 return XMLHandle( _node
? _node
->PreviousSibling() : 0 );
1829 /// Get the previous sibling element of this handle.
1830 XMLHandle
PreviousSiblingElement( const char* name
= 0 ) {
1831 return XMLHandle( _node
? _node
->PreviousSiblingElement( name
) : 0 );
1833 /// Get the next sibling of this handle.
1834 XMLHandle
NextSibling() {
1835 return XMLHandle( _node
? _node
->NextSibling() : 0 );
1837 /// Get the next sibling element of this handle.
1838 XMLHandle
NextSiblingElement( const char* name
= 0 ) {
1839 return XMLHandle( _node
? _node
->NextSiblingElement( name
) : 0 );
1842 /// Safe cast to XMLNode. This can return null.
1846 /// Safe cast to XMLElement. This can return null.
1847 XMLElement
* ToElement() {
1848 return ( ( _node
== 0 ) ? 0 : _node
->ToElement() );
1850 /// Safe cast to XMLText. This can return null.
1852 return ( ( _node
== 0 ) ? 0 : _node
->ToText() );
1854 /// Safe cast to XMLUnknown. This can return null.
1855 XMLUnknown
* ToUnknown() {
1856 return ( ( _node
== 0 ) ? 0 : _node
->ToUnknown() );
1858 /// Safe cast to XMLDeclaration. This can return null.
1859 XMLDeclaration
* ToDeclaration() {
1860 return ( ( _node
== 0 ) ? 0 : _node
->ToDeclaration() );
1869 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1870 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1872 class TINYXML2_LIB XMLConstHandle
1875 XMLConstHandle( const XMLNode
* node
) {
1878 XMLConstHandle( const XMLNode
& node
) {
1881 XMLConstHandle( const XMLConstHandle
& ref
) {
1885 XMLConstHandle
& operator=( const XMLConstHandle
& ref
) {
1890 const XMLConstHandle
FirstChild() const {
1891 return XMLConstHandle( _node
? _node
->FirstChild() : 0 );
1893 const XMLConstHandle
FirstChildElement( const char* name
= 0 ) const {
1894 return XMLConstHandle( _node
? _node
->FirstChildElement( name
) : 0 );
1896 const XMLConstHandle
LastChild() const {
1897 return XMLConstHandle( _node
? _node
->LastChild() : 0 );
1899 const XMLConstHandle
LastChildElement( const char* name
= 0 ) const {
1900 return XMLConstHandle( _node
? _node
->LastChildElement( name
) : 0 );
1902 const XMLConstHandle
PreviousSibling() const {
1903 return XMLConstHandle( _node
? _node
->PreviousSibling() : 0 );
1905 const XMLConstHandle
PreviousSiblingElement( const char* name
= 0 ) const {
1906 return XMLConstHandle( _node
? _node
->PreviousSiblingElement( name
) : 0 );
1908 const XMLConstHandle
NextSibling() const {
1909 return XMLConstHandle( _node
? _node
->NextSibling() : 0 );
1911 const XMLConstHandle
NextSiblingElement( const char* name
= 0 ) const {
1912 return XMLConstHandle( _node
? _node
->NextSiblingElement( name
) : 0 );
1916 const XMLNode
* ToNode() const {
1919 const XMLElement
* ToElement() const {
1920 return ( ( _node
== 0 ) ? 0 : _node
->ToElement() );
1922 const XMLText
* ToText() const {
1923 return ( ( _node
== 0 ) ? 0 : _node
->ToText() );
1925 const XMLUnknown
* ToUnknown() const {
1926 return ( ( _node
== 0 ) ? 0 : _node
->ToUnknown() );
1928 const XMLDeclaration
* ToDeclaration() const {
1929 return ( ( _node
== 0 ) ? 0 : _node
->ToDeclaration() );
1933 const XMLNode
* _node
;
1938 Printing functionality. The XMLPrinter gives you more
1939 options than the XMLDocument::Print() method.
1943 -# Print to a file you provide.
1944 -# Print XML without a XMLDocument.
1950 doc.Print( &printer );
1951 SomeFunction( printer.CStr() );
1956 You provide the file pointer.
1958 XMLPrinter printer( fp );
1959 doc.Print( &printer );
1962 Print without a XMLDocument
1964 When loading, an XML parser is very useful. However, sometimes
1965 when saving, it just gets in the way. The code is often set up
1966 for streaming, and constructing the DOM is just overhead.
1968 The Printer supports the streaming case. The following code
1969 prints out a trivially simple XML file without ever creating
1973 XMLPrinter printer( fp );
1974 printer.OpenElement( "foo" );
1975 printer.PushAttribute( "foo", "bar" );
1976 printer.CloseElement();
1979 class TINYXML2_LIB XMLPrinter
: public XMLVisitor
1982 /** Construct the printer. If the FILE* is specified,
1983 this will print to the FILE. Else it will print
1984 to memory, and the result is available in CStr().
1985 If 'compact' is set to true, then output is created
1986 with only required whitespace and newlines.
1988 XMLPrinter( FILE* file
=0, bool compact
= false, int depth
= 0 );
1989 virtual ~XMLPrinter() {}
1991 /** If streaming, write the BOM and declaration. */
1992 void PushHeader( bool writeBOM
, bool writeDeclaration
);
1993 /** If streaming, start writing an element.
1994 The element must be closed with CloseElement()
1996 void OpenElement( const char* name
, bool compactMode
=false );
1997 /// If streaming, add an attribute to an open element.
1998 void PushAttribute( const char* name
, const char* value
);
1999 void PushAttribute( const char* name
, int value
);
2000 void PushAttribute( const char* name
, unsigned value
);
2001 void PushAttribute( const char* name
, bool value
);
2002 void PushAttribute( const char* name
, double value
);
2003 /// If streaming, close the Element.
2004 virtual void CloseElement( bool compactMode
=false );
2006 /// Add a text node.
2007 void PushText( const char* text
, bool cdata
=false );
2008 /// Add a text node from an integer.
2009 void PushText( int value
);
2010 /// Add a text node from an unsigned.
2011 void PushText( unsigned value
);
2012 /// Add a text node from a bool.
2013 void PushText( bool value
);
2014 /// Add a text node from a float.
2015 void PushText( float value
);
2016 /// Add a text node from a double.
2017 void PushText( double value
);
2020 void PushComment( const char* comment
);
2022 void PushDeclaration( const char* value
);
2023 void PushUnknown( const char* value
);
2025 virtual bool VisitEnter( const XMLDocument
& /*doc*/ );
2026 virtual bool VisitExit( const XMLDocument
& /*doc*/ ) {
2030 virtual bool VisitEnter( const XMLElement
& element
, const XMLAttribute
* attribute
);
2031 virtual bool VisitExit( const XMLElement
& element
);
2033 virtual bool Visit( const XMLText
& text
);
2034 virtual bool Visit( const XMLComment
& comment
);
2035 virtual bool Visit( const XMLDeclaration
& declaration
);
2036 virtual bool Visit( const XMLUnknown
& unknown
);
2039 If in print to memory mode, return a pointer to
2040 the XML file in memory.
2042 const char* CStr() const {
2043 return _buffer
.Mem();
2046 If in print to memory mode, return the size
2047 of the XML file in memory. (Note the size returned
2048 includes the terminating null.)
2050 int CStrSize() const {
2051 return _buffer
.Size();
2054 If in print to memory mode, reset the buffer to the
2057 void ClearBuffer() {
2063 virtual bool CompactMode( const XMLElement
& ) { return _compactMode
; }
2065 /** Prints out the space before an element. You may override to change
2066 the space and tabs used. A PrintSpace() override should call Print().
2068 virtual void PrintSpace( int depth
);
2069 void Print( const char* format
, ... );
2071 void SealElementIfJustOpened();
2072 bool _elementJustOpened
;
2073 DynArray
< const char*, 10 > _stack
;
2076 void PrintString( const char*, bool restrictedEntitySet
); // prints out, after detecting entities.
2082 bool _processEntities
;
2089 bool _entityFlag
[ENTITY_RANGE
];
2090 bool _restrictedEntityFlag
[ENTITY_RANGE
];
2092 DynArray
< char, 20 > _buffer
;
2098 #if defined(_MSC_VER)
2099 # pragma warning(pop)
2102 #endif // TINYXML2_INCLUDED