1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original code by Lee Thomason (www.grinninglizard.com)
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12 
13 1. The origin of this software must not be misrepresented; you must
14 not claim that you wrote the original software. If you use this
15 software in a product, an acknowledgment in the product documentation
16 would be appreciated but is not required.
17 
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20 
21 3. This notice may not be removed or altered from any source
22 distribution.
23 
24 
25 Modified:  Copyright (C) 2009 Alois Schloegl <a.schloegl@ieee.org>
26 add support for zlib-compressed (gzipped) XML data
27 
28     $Id: tinyxml.h,v 1.5 2009/04/09 09:12:09 schloegl Exp $
29     Copyright (C) 2009,2011 Alois Schloegl <a.schloegl@ieee.org>
30     This file is part of the "BioSig for C/C++" repository
31     (biosig4c++) at http://biosig.sf.net/
32 
33     BioSig is free software; you can redistribute it and/or
34     modify it under the terms of the GNU General Public License
35     as published by the Free Software Foundation; either version 3
36     of the License, or (at your option) any later version.
37 
38 */
39 
40 #include <ctype.h>
41 #include <iconv.h>
42 
43 #ifdef TIXML_USE_STL
44 #include <sstream>
45 #include <iostream>
46 #endif
47 
48 #include "tinyxml.h"
49 
50 FILE* TiXmlFOpen( const char* filename, const char* mode );
51 
52 bool TiXmlBase::condenseWhiteSpace = true;
53 
54 // Microsoft compiler security
TiXmlFOpen(const char * filename,const char * mode)55 FILE* TiXmlFOpen( const char* filename, const char* mode )
56 {
57 	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
58 		FILE* fp = 0;
59 		errno_t err = fopen_s( &fp, filename, mode );
60 		if ( !err && fp )
61 			return fp;
62 		return 0;
63 	#else
64 		return fopen( filename, mode );
65 	#endif
66 }
67 
EncodeString(const TIXML_STRING & str,TIXML_STRING * outString)68 void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
69 {
70 	int i=0;
71 
72 	while( i<(int)str.length() )
73 	{
74 		unsigned char c = (unsigned char) str[i];
75 
76 		if (    c == '&'
77 		     && i < ( (int)str.length() - 2 )
78 			 && str[i+1] == '#'
79 			 && str[i+2] == 'x' )
80 		{
81 			// Hexadecimal character reference.
82 			// Pass through unchanged.
83 			// &#xA9;	-- copyright symbol, for example.
84 			//
85 			// The -1 is a bug fix from Rob Laveaux. It keeps
86 			// an overflow from happening if there is no ';'.
87 			// There are actually 2 ways to exit this loop -
88 			// while fails (error case) and break (semicolon found).
89 			// However, there is no mechanism (currently) for
90 			// this function to return an error.
91 			while ( i<(int)str.length()-1 )
92 			{
93 				outString->append( str.c_str() + i, 1 );
94 				++i;
95 				if ( str[i] == ';' )
96 					break;
97 			}
98 		}
99 		else if ( c == '&' )
100 		{
101 			outString->append( entity[0].str, entity[0].strLength );
102 			++i;
103 		}
104 		else if ( c == '<' )
105 		{
106 			outString->append( entity[1].str, entity[1].strLength );
107 			++i;
108 		}
109 		else if ( c == '>' )
110 		{
111 			outString->append( entity[2].str, entity[2].strLength );
112 			++i;
113 		}
114 		else if ( c == '\"' )
115 		{
116 			outString->append( entity[3].str, entity[3].strLength );
117 			++i;
118 		}
119 		else if ( c == '\'' )
120 		{
121 			outString->append( entity[4].str, entity[4].strLength );
122 			++i;
123 		}
124 		else if ( c < 32 )
125 		{
126 			// Easy pass at non-alpha/numeric/symbol
127 			// Below 32 is symbolic.
128 			char buf[ 32 ];
129 
130 			#if defined(TIXML_SNPRINTF)
131 				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
132 			#else
133 				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
134 			#endif
135 
136 			//*ME:	warning C4267: convert 'size_t' to 'int'
137 			//*ME:	Int-Cast to make compiler happy ...
138 			outString->append( buf, (int)strlen( buf ) );
139 			++i;
140 		}
141 		else
142 		{
143 			//char realc = (char) c;
144 			//outString->append( &realc, 1 );
145 			*outString += (char) c;	// somewhat more efficient function call.
146 			++i;
147 		}
148 	}
149 }
150 
151 
TiXmlNode(NodeType _type)152 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
153 {
154 	parent = 0;
155 	type = _type;
156 	firstChild = 0;
157 	lastChild = 0;
158 	prev = 0;
159 	next = 0;
160 }
161 
162 
~TiXmlNode()163 TiXmlNode::~TiXmlNode()
164 {
165 	TiXmlNode* node = firstChild;
166 	TiXmlNode* temp = 0;
167 
168 	while ( node )
169 	{
170 		temp = node;
171 		node = node->next;
172 		delete temp;
173 	}
174 }
175 
176 
CopyTo(TiXmlNode * target) const177 void TiXmlNode::CopyTo( TiXmlNode* target ) const
178 {
179 	target->SetValue (value.c_str() );
180 	target->userData = userData;
181 	target->location = location;
182 }
183 
184 
Clear()185 void TiXmlNode::Clear()
186 {
187 	TiXmlNode* node = firstChild;
188 	TiXmlNode* temp = 0;
189 
190 	while ( node )
191 	{
192 		temp = node;
193 		node = node->next;
194 		delete temp;
195 	}
196 
197 	firstChild = 0;
198 	lastChild = 0;
199 }
200 
201 
LinkEndChild(TiXmlNode * node)202 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
203 {
204 	assert( node->parent == 0 || node->parent == this );
205 	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
206 
207 	if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
208 	{
209 		delete node;
210 		if ( GetDocument() )
211 			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
212 		return 0;
213 	}
214 
215 	node->parent = this;
216 
217 	node->prev = lastChild;
218 	node->next = 0;
219 
220 	if ( lastChild )
221 		lastChild->next = node;
222 	else
223 		firstChild = node;			// it was an empty list.
224 
225 	lastChild = node;
226 	return node;
227 }
228 
229 
InsertEndChild(const TiXmlNode & addThis)230 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
231 {
232 	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
233 	{
234 		if ( GetDocument() )
235 			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
236 		return 0;
237 	}
238 	TiXmlNode* node = addThis.Clone();
239 	if ( !node )
240 		return 0;
241 
242 	return LinkEndChild( node );
243 }
244 
245 
InsertBeforeChild(TiXmlNode * beforeThis,const TiXmlNode & addThis)246 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
247 {
248 	if ( !beforeThis || beforeThis->parent != this ) {
249 		return 0;
250 	}
251 	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
252 	{
253 		if ( GetDocument() )
254 			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
255 		return 0;
256 	}
257 
258 	TiXmlNode* node = addThis.Clone();
259 	if ( !node )
260 		return 0;
261 	node->parent = this;
262 
263 	node->next = beforeThis;
264 	node->prev = beforeThis->prev;
265 	if ( beforeThis->prev )
266 	{
267 		beforeThis->prev->next = node;
268 	}
269 	else
270 	{
271 		assert( firstChild == beforeThis );
272 		firstChild = node;
273 	}
274 	beforeThis->prev = node;
275 	return node;
276 }
277 
278 
InsertAfterChild(TiXmlNode * afterThis,const TiXmlNode & addThis)279 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
280 {
281 	if ( !afterThis || afterThis->parent != this ) {
282 		return 0;
283 	}
284 	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
285 	{
286 		if ( GetDocument() )
287 			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
288 		return 0;
289 	}
290 
291 	TiXmlNode* node = addThis.Clone();
292 	if ( !node )
293 		return 0;
294 	node->parent = this;
295 
296 	node->prev = afterThis;
297 	node->next = afterThis->next;
298 	if ( afterThis->next )
299 	{
300 		afterThis->next->prev = node;
301 	}
302 	else
303 	{
304 		assert( lastChild == afterThis );
305 		lastChild = node;
306 	}
307 	afterThis->next = node;
308 	return node;
309 }
310 
311 
ReplaceChild(TiXmlNode * replaceThis,const TiXmlNode & withThis)312 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
313 {
314 	if ( !replaceThis )
315 		return 0;
316 
317 	if ( replaceThis->parent != this )
318 		return 0;
319 
320 	if ( withThis.ToDocument() ) {
321 		// A document can never be a child.	Thanks to Noam.
322 		TiXmlDocument* document = GetDocument();
323 		if ( document )
324 			document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
325 		return 0;
326 	}
327 
328 	TiXmlNode* node = withThis.Clone();
329 	if ( !node )
330 		return 0;
331 
332 	node->next = replaceThis->next;
333 	node->prev = replaceThis->prev;
334 
335 	if ( replaceThis->next )
336 		replaceThis->next->prev = node;
337 	else
338 		lastChild = node;
339 
340 	if ( replaceThis->prev )
341 		replaceThis->prev->next = node;
342 	else
343 		firstChild = node;
344 
345 	delete replaceThis;
346 	node->parent = this;
347 	return node;
348 }
349 
350 
RemoveChild(TiXmlNode * removeThis)351 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
352 {
353 	if ( !removeThis ) {
354 		return false;
355 	}
356 
357 	if ( removeThis->parent != this )
358 	{
359 		assert( 0 );
360 		return false;
361 	}
362 
363 	if ( removeThis->next )
364 		removeThis->next->prev = removeThis->prev;
365 	else
366 		lastChild = removeThis->prev;
367 
368 	if ( removeThis->prev )
369 		removeThis->prev->next = removeThis->next;
370 	else
371 		firstChild = removeThis->next;
372 
373 	delete removeThis;
374 	return true;
375 }
376 
FirstChild(const char * _value) const377 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
378 {
379 	const TiXmlNode* node;
380 	for ( node = firstChild; node; node = node->next )
381 	{
382 		if ( strcmp( node->Value(), _value ) == 0 )
383 			return node;
384 	}
385 	return 0;
386 }
387 
388 
LastChild(const char * _value) const389 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
390 {
391 	const TiXmlNode* node;
392 	for ( node = lastChild; node; node = node->prev )
393 	{
394 		if ( strcmp( node->Value(), _value ) == 0 )
395 			return node;
396 	}
397 	return 0;
398 }
399 
400 
IterateChildren(const TiXmlNode * previous) const401 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
402 {
403 	if ( !previous )
404 	{
405 		return FirstChild();
406 	}
407 	else
408 	{
409 		assert( previous->parent == this );
410 		return previous->NextSibling();
411 	}
412 }
413 
414 
IterateChildren(const char * val,const TiXmlNode * previous) const415 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
416 {
417 	if ( !previous )
418 	{
419 		return FirstChild( val );
420 	}
421 	else
422 	{
423 		assert( previous->parent == this );
424 		return previous->NextSibling( val );
425 	}
426 }
427 
428 
NextSibling(const char * _value) const429 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
430 {
431 	const TiXmlNode* node;
432 	for ( node = next; node; node = node->next )
433 	{
434 		if ( strcmp( node->Value(), _value ) == 0 )
435 			return node;
436 	}
437 	return 0;
438 }
439 
440 
PreviousSibling(const char * _value) const441 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
442 {
443 	const TiXmlNode* node;
444 	for ( node = prev; node; node = node->prev )
445 	{
446 		if ( strcmp( node->Value(), _value ) == 0 )
447 			return node;
448 	}
449 	return 0;
450 }
451 
452 
RemoveAttribute(const char * name)453 void TiXmlElement::RemoveAttribute( const char * name )
454 {
455     #ifdef TIXML_USE_STL
456 	TIXML_STRING str( name );
457 	TiXmlAttribute* node = attributeSet.Find( str );
458 	#else
459 	TiXmlAttribute* node = attributeSet.Find( name );
460 	#endif
461 	if ( node )
462 	{
463 		attributeSet.Remove( node );
464 		delete node;
465 	}
466 }
467 
FirstChildElement() const468 const TiXmlElement* TiXmlNode::FirstChildElement() const
469 {
470 	const TiXmlNode* node;
471 
472 	for (	node = FirstChild();
473 			node;
474 			node = node->NextSibling() )
475 	{
476 		if ( node->ToElement() )
477 			return node->ToElement();
478 	}
479 	return 0;
480 }
481 
482 
FirstChildElement(const char * _value) const483 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
484 {
485 	const TiXmlNode* node;
486 
487 	for (	node = FirstChild( _value );
488 			node;
489 			node = node->NextSibling( _value ) )
490 	{
491 		if ( node->ToElement() )
492 			return node->ToElement();
493 	}
494 	return 0;
495 }
496 
497 
NextSiblingElement() const498 const TiXmlElement* TiXmlNode::NextSiblingElement() const
499 {
500 	const TiXmlNode* node;
501 
502 	for (	node = NextSibling();
503 			node;
504 			node = node->NextSibling() )
505 	{
506 		if ( node->ToElement() )
507 			return node->ToElement();
508 	}
509 	return 0;
510 }
511 
512 
NextSiblingElement(const char * _value) const513 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
514 {
515 	const TiXmlNode* node;
516 
517 	for (	node = NextSibling( _value );
518 			node;
519 			node = node->NextSibling( _value ) )
520 	{
521 		if ( node->ToElement() )
522 			return node->ToElement();
523 	}
524 	return 0;
525 }
526 
527 
GetDocument() const528 const TiXmlDocument* TiXmlNode::GetDocument() const
529 {
530 	const TiXmlNode* node;
531 
532 	for( node = this; node; node = node->parent )
533 	{
534 		if ( node->ToDocument() )
535 			return node->ToDocument();
536 	}
537 	return 0;
538 }
539 
540 
TiXmlElement(const char * _value)541 TiXmlElement::TiXmlElement (const char * _value)
542 	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
543 {
544 	firstChild = lastChild = 0;
545 	value = _value;
546 }
547 
548 
549 #ifdef TIXML_USE_STL
TiXmlElement(const std::string & _value)550 TiXmlElement::TiXmlElement( const std::string& _value )
551 	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
552 {
553 	firstChild = lastChild = 0;
554 	value = _value;
555 }
556 #endif
557 
558 
TiXmlElement(const TiXmlElement & copy)559 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
560 	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
561 {
562 	firstChild = lastChild = 0;
563 	copy.CopyTo( this );
564 }
565 
566 
operator =(const TiXmlElement & base)567 TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
568 {
569 	ClearThis();
570 	base.CopyTo( this );
571 	return *this;
572 }
573 
574 
~TiXmlElement()575 TiXmlElement::~TiXmlElement()
576 {
577 	ClearThis();
578 }
579 
580 
ClearThis()581 void TiXmlElement::ClearThis()
582 {
583 	Clear();
584 	while( attributeSet.First() )
585 	{
586 		TiXmlAttribute* node = attributeSet.First();
587 		attributeSet.Remove( node );
588 		delete node;
589 	}
590 }
591 
592 
Attribute(const char * name) const593 const char* TiXmlElement::Attribute( const char* name ) const
594 {
595 	const TiXmlAttribute* node = attributeSet.Find( name );
596 	if ( node )
597 		return node->Value();
598 	return 0;
599 }
600 
601 
602 #ifdef TIXML_USE_STL
Attribute(const std::string & name) const603 const std::string* TiXmlElement::Attribute( const std::string& name ) const
604 {
605 	const TiXmlAttribute* attrib = attributeSet.Find( name );
606 	if ( attrib )
607 		return &attrib->ValueStr();
608 	return 0;
609 }
610 #endif
611 
612 
Attribute(const char * name,int * i) const613 const char* TiXmlElement::Attribute( const char* name, int* i ) const
614 {
615 	const TiXmlAttribute* attrib = attributeSet.Find( name );
616 	const char* result = 0;
617 
618 	if ( attrib ) {
619 		result = attrib->Value();
620 		if ( i ) {
621 			attrib->QueryIntValue( i );
622 		}
623 	}
624 	return result;
625 }
626 
627 
628 #ifdef TIXML_USE_STL
Attribute(const std::string & name,int * i) const629 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
630 {
631 	const TiXmlAttribute* attrib = attributeSet.Find( name );
632 	const std::string* result = 0;
633 
634 	if ( attrib ) {
635 		result = &attrib->ValueStr();
636 		if ( i ) {
637 			attrib->QueryIntValue( i );
638 		}
639 	}
640 	return result;
641 }
642 #endif
643 
644 
Attribute(const char * name,double * d) const645 const char* TiXmlElement::Attribute( const char* name, double* d ) const
646 {
647 	const TiXmlAttribute* attrib = attributeSet.Find( name );
648 	const char* result = 0;
649 
650 	if ( attrib ) {
651 		result = attrib->Value();
652 		if ( d ) {
653 			attrib->QueryDoubleValue( d );
654 		}
655 	}
656 	return result;
657 }
658 
659 
660 #ifdef TIXML_USE_STL
Attribute(const std::string & name,double * d) const661 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
662 {
663 	const TiXmlAttribute* attrib = attributeSet.Find( name );
664 	const std::string* result = 0;
665 
666 	if ( attrib ) {
667 		result = &attrib->ValueStr();
668 		if ( d ) {
669 			attrib->QueryDoubleValue( d );
670 		}
671 	}
672 	return result;
673 }
674 #endif
675 
676 
QueryIntAttribute(const char * name,int * ival) const677 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
678 {
679 	const TiXmlAttribute* attrib = attributeSet.Find( name );
680 	if ( !attrib )
681 		return TIXML_NO_ATTRIBUTE;
682 	return attrib->QueryIntValue( ival );
683 }
684 
685 
QueryUnsignedAttribute(const char * name,unsigned * value) const686 int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const
687 {
688 	const TiXmlAttribute* node = attributeSet.Find( name );
689 	if ( !node )
690 		return TIXML_NO_ATTRIBUTE;
691 
692 	int ival = 0;
693 	int result = node->QueryIntValue( &ival );
694 	*value = (unsigned)ival;
695 	return result;
696 }
697 
698 
QueryBoolAttribute(const char * name,bool * bval) const699 int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const
700 {
701 	const TiXmlAttribute* node = attributeSet.Find( name );
702 	if ( !node )
703 		return TIXML_NO_ATTRIBUTE;
704 
705 	int result = TIXML_WRONG_TYPE;
706 	if (    StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN )
707 		 || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN )
708 		 || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) )
709 	{
710 		*bval = true;
711 		result = TIXML_SUCCESS;
712 	}
713 	else if (    StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN )
714 			  || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN )
715 			  || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) )
716 	{
717 		*bval = false;
718 		result = TIXML_SUCCESS;
719 	}
720 	return result;
721 }
722 
723 
724 
725 #ifdef TIXML_USE_STL
QueryIntAttribute(const std::string & name,int * ival) const726 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
727 {
728 	const TiXmlAttribute* attrib = attributeSet.Find( name );
729 	if ( !attrib )
730 		return TIXML_NO_ATTRIBUTE;
731 	return attrib->QueryIntValue( ival );
732 }
733 #endif
734 
735 
QueryDoubleAttribute(const char * name,double * dval) const736 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
737 {
738 	const TiXmlAttribute* attrib = attributeSet.Find( name );
739 	if ( !attrib )
740 		return TIXML_NO_ATTRIBUTE;
741 	return attrib->QueryDoubleValue( dval );
742 }
743 
744 
745 #ifdef TIXML_USE_STL
QueryDoubleAttribute(const std::string & name,double * dval) const746 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
747 {
748 	const TiXmlAttribute* attrib = attributeSet.Find( name );
749 	if ( !attrib )
750 		return TIXML_NO_ATTRIBUTE;
751 	return attrib->QueryDoubleValue( dval );
752 }
753 #endif
754 
755 
SetAttribute(const char * name,int val)756 void TiXmlElement::SetAttribute( const char * name, int val )
757 {
758 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
759 	if ( attrib ) {
760 		attrib->SetIntValue( val );
761 	}
762 }
763 
764 
765 #ifdef TIXML_USE_STL
SetAttribute(const std::string & name,int val)766 void TiXmlElement::SetAttribute( const std::string& name, int val )
767 {
768 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
769 	if ( attrib ) {
770 		attrib->SetIntValue( val );
771 	}
772 }
773 #endif
774 
775 
SetDoubleAttribute(const char * name,double val)776 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
777 {
778 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
779 	if ( attrib ) {
780 		attrib->SetDoubleValue( val );
781 	}
782 }
783 
784 
785 #ifdef TIXML_USE_STL
SetDoubleAttribute(const std::string & name,double val)786 void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
787 {
788 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
789 	if ( attrib ) {
790 		attrib->SetDoubleValue( val );
791 	}
792 }
793 #endif
794 
795 
SetAttribute(const char * cname,const char * cvalue)796 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
797 {
798 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
799 	if ( attrib ) {
800 		attrib->SetValue( cvalue );
801 	}
802 }
803 
804 
805 #ifdef TIXML_USE_STL
SetAttribute(const std::string & _name,const std::string & _value)806 void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
807 {
808 	TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
809 	if ( attrib ) {
810 		attrib->SetValue( _value );
811 	}
812 }
813 #endif
814 
815 
Print(FILE * cfile,int depth) const816 void TiXmlElement::Print( FILE* cfile, int depth ) const
817 {
818 	int i;
819 	assert( cfile );
820 	for ( i=0; i<depth; i++ ) {
821 		fprintf( cfile, "    " );
822 	}
823 
824 	fprintf( cfile, "<%s", value.c_str() );
825 
826 	const TiXmlAttribute* attrib;
827 	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
828 	{
829 		fprintf( cfile, " " );
830 		attrib->Print( cfile, depth );
831 	}
832 
833 	// There are 3 different formatting approaches:
834 	// 1) An element without children is printed as a <foo /> node
835 	// 2) An element with only a text child is printed as <foo> text </foo>
836 	// 3) An element with children is printed on multiple lines.
837 	TiXmlNode* node;
838 	if ( !firstChild )
839 	{
840 		fprintf( cfile, " />" );
841 	}
842 	else if ( firstChild == lastChild && firstChild->ToText() )
843 	{
844 		fprintf( cfile, ">" );
845 		firstChild->Print( cfile, depth + 1 );
846 		fprintf( cfile, "</%s>", value.c_str() );
847 	}
848 	else
849 	{
850 		fprintf( cfile, ">" );
851 
852 		for ( node = firstChild; node; node=node->NextSibling() )
853 		{
854 			if ( !node->ToText() )
855 			{
856 				fprintf( cfile, "\n" );
857 			}
858 			node->Print( cfile, depth+1 );
859 		}
860 		fprintf( cfile, "\n" );
861 		for( i=0; i<depth; ++i ) {
862 			fprintf( cfile, "    " );
863 		}
864 		fprintf( cfile, "</%s>", value.c_str() );
865 	}
866 }
867 
868 #ifdef ZLIB_H
gzPrint(gzFile cfile,int depth) const869 void TiXmlElement::gzPrint( gzFile cfile, int depth ) const
870 {
871 	int i;
872 	assert( cfile );
873 	for ( i=0; i<depth; i++ ) {
874 		gzprintf( cfile, "    " );
875 	}
876 
877 	gzprintf( cfile, "<%s", value.c_str() );
878 
879 	const TiXmlAttribute* attrib;
880 	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
881 	{
882 		gzprintf( cfile, " " );
883 		attrib->gzPrint( cfile, depth );
884 	}
885 
886 	// There are 3 different formatting approaches:
887 	// 1) An element without children is printed as a <foo /> node
888 	// 2) An element with only a text child is printed as <foo> text </foo>
889 	// 3) An element with children is printed on multiple lines.
890 	TiXmlNode* node;
891 	if ( !firstChild )
892 	{
893 		gzprintf( cfile, " />" );
894 	}
895 	else if ( firstChild == lastChild && firstChild->ToText() )
896 	{
897 		gzprintf( cfile, ">" );
898 		firstChild->gzPrint( cfile, depth + 1 );
899 		gzprintf( cfile, "</%s>", value.c_str() );
900 	}
901 	else
902 	{
903 		gzprintf( cfile, ">" );
904 
905 		for ( node = firstChild; node; node=node->NextSibling() )
906 		{
907 			if ( !node->ToText() )
908 			{
909 				gzprintf( cfile, "\n" );
910 			}
911 			node->gzPrint( cfile, depth+1 );
912 		}
913 		gzprintf( cfile, "\n" );
914 		for( i=0; i<depth; ++i ) {
915 			gzprintf( cfile, "    " );
916 		}
917 		gzprintf( cfile, "</%s>", value.c_str() );
918 	}
919 }
920 #endif
921 
922 
CopyTo(TiXmlElement * target) const923 void TiXmlElement::CopyTo( TiXmlElement* target ) const
924 {
925 	// superclass:
926 	TiXmlNode::CopyTo( target );
927 
928 	// Element class:
929 	// Clone the attributes, then clone the children.
930 	const TiXmlAttribute* attribute = 0;
931 	for(	attribute = attributeSet.First();
932 	attribute;
933 	attribute = attribute->Next() )
934 	{
935 		target->SetAttribute( attribute->Name(), attribute->Value() );
936 	}
937 
938 	TiXmlNode* node = 0;
939 	for ( node = firstChild; node; node = node->NextSibling() )
940 	{
941 		target->LinkEndChild( node->Clone() );
942 	}
943 }
944 
Accept(TiXmlVisitor * visitor) const945 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
946 {
947 	if ( visitor->VisitEnter( *this, attributeSet.First() ) )
948 	{
949 		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
950 		{
951 			if ( !node->Accept( visitor ) )
952 				break;
953 		}
954 	}
955 	return visitor->VisitExit( *this );
956 }
957 
958 
Clone() const959 TiXmlNode* TiXmlElement::Clone() const
960 {
961 	TiXmlElement* clone = new TiXmlElement( Value() );
962 	if ( !clone )
963 		return 0;
964 
965 	CopyTo( clone );
966 	return clone;
967 }
968 
969 
GetText() const970 const char* TiXmlElement::GetText() const
971 {
972 	const TiXmlNode* child = this->FirstChild();
973 	if ( child ) {
974 		const TiXmlText* childText = child->ToText();
975 		if ( childText ) {
976 			return childText->Value();
977 		}
978 	}
979 	return 0;
980 }
981 
982 
TiXmlDocument()983 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
984 {
985 	tabsize = 4;
986 	useMicrosoftBOM = false;
987 	ClearError();
988 }
989 
TiXmlDocument(const char * documentName)990 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
991 {
992 	tabsize = 4;
993 	useMicrosoftBOM = false;
994 	value = documentName;
995 	ClearError();
996 }
997 
998 
999 #ifdef TIXML_USE_STL
TiXmlDocument(const std::string & documentName)1000 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
1001 {
1002 	tabsize = 4;
1003 	useMicrosoftBOM = false;
1004     value = documentName;
1005 	ClearError();
1006 }
1007 #endif
1008 
1009 
TiXmlDocument(const TiXmlDocument & copy)1010 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
1011 {
1012 	copy.CopyTo( this );
1013 }
1014 
1015 
operator =(const TiXmlDocument & copy)1016 TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
1017 {
1018 	Clear();
1019 	copy.CopyTo( this );
1020 	return *this;
1021 }
1022 
1023 
LoadFile(TiXmlEncoding encoding)1024 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
1025 {
1026 	return LoadFile( Value(), encoding );
1027 }
1028 
1029 
SaveFile() const1030 bool TiXmlDocument::SaveFile() const
1031 {
1032 	return SaveFile( Value() );
1033 }
1034 
LoadFile(const char * _filename,TiXmlEncoding encoding)1035 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
1036 {
1037 	TIXML_STRING filename( _filename );
1038 	value = filename;
1039 
1040 	// reading in binary mode so that tinyxml can normalize the EOL
1041 #ifdef ZLIB_H
1042 	gzFile file;
1043 	file = gzopen( value.c_str(), "rb" );
1044 	if ( file )
1045 	{
1046 		bool result = LoadFile( file, encoding );
1047 		gzclose( file );
1048 		return result;
1049 	}
1050 #else
1051 	FILE* file = TiXmlFOpen( value.c_str (), "rb" );
1052 
1053 	if ( file )
1054 	{
1055 		bool result = LoadFile( file, encoding );
1056 		fclose( file );
1057 		return result;
1058 	}
1059 #endif
1060 	else
1061 	{
1062 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1063 		return false;
1064 	}
1065 }
1066 
LoadFile(FILE * file,TiXmlEncoding encoding)1067 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
1068 {
1069 	if ( !file )
1070 	{
1071 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1072 		return false;
1073 	}
1074 
1075 	// Delete the existing data:
1076 	Clear();
1077 	location.Clear();
1078 
1079 	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
1080 	size_t length = 0;
1081 	fseek( file, 0, SEEK_END );
1082 	length = ftell( file );
1083 	fseek( file, 0, SEEK_SET );
1084 
1085 	// Strange case, but good to handle up front.
1086 	if ( length <= 0 )
1087 	{
1088 		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
1089 		return false;
1090 	}
1091 
1092 	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
1093 	// 2.11 End-of-Line Handling
1094 	// <snip>
1095 	// <quote>
1096 	// ...the XML processor MUST behave as if it normalized all line breaks in external
1097 	// parsed entities (including the document entity) on input, before parsing, by translating
1098 	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1099 	// a single #xA character.
1100 	// </quote>
1101 	//
1102 	// It is not clear fgets does that, and certainly isn't clear it works cross platform.
1103 	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
1104 	// convention, and not work generally.
1105 
1106 	/*
1107 	while( fgets( buf, sizeof(buf), file ) )
1108 	{
1109 		data += buf;
1110 	}
1111 	*/
1112 
1113 	char* buf = new char[ length+1 ];
1114 	buf[0] = 0;
1115 
1116 	if ( fread( buf, length, 1, file ) != 1 ) {
1117 		delete [] buf;
1118 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1119 		return false;
1120 	}
1121 
1122 
1123 #if defined(_ICONV_H) || defined (_LIBICONV_H)
1124 	// convert utf-16 to utf-8 if needed
1125 
1126 	const char XML_UTF16LE[] = "\xff\xfe<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0\"\0001\0.\0000\0\"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0\"\0U\0T\0F\0-\0001\0006\0\"\0?\0>\0";
1127 	if (!memcmp(buf, XML_UTF16LE, sizeof(XML_UTF16LE)-1 ) ) {
1128 		char *buf2 = (char*)malloc(length);
1129 		size_t outlen = length;
1130 
1131 		char *inbuf = buf;
1132 		char *outbuf = buf2;
1133 		iconv_t CD = iconv_open ("UTF-8","UTF-16LE");
1134 		size_t iconv_res = iconv (CD, &inbuf, &length, &outbuf, &outlen);
1135 		iconv_close (CD);
1136 
1137 		if (iconv_res != (size_t)(-1)) {
1138 			free(buf);
1139 			outbuf[0] = 0;
1140 			buf = buf2;
1141 			length = strlen(buf);
1142 		}
1143 		else {
1144 			free(buf2);
1145 			fprintf(stderr,"SOPEN_HL7aECG: attempt to convert UTF-16 to UTF-8 failed\n");
1146 		}
1147 	}
1148 #else
1149 	fprintf(stderr,"SOPEN_HL7aECG: conversion of UTF-16 to UTF-8 is not supported\n");
1150 #endif
1151 
1152 
1153 	// Process the buffer in place to normalize new lines. (See comment above.)
1154 	// Copies from the 'p' to 'q' pointer, where p can advance faster if
1155 	// a newline-carriage return is hit.
1156 	//
1157 	// Wikipedia:
1158 	// Systems based on ASCII or a compatible character set use either LF  (Line feed, '\n', 0x0A, 10 in decimal) or
1159 	// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
1160 	//		* LF:    Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
1161     //		* CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
1162     //		* CR:    Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
1163 
1164 	const char* p = buf;	// the read head
1165 	char* q = buf;			// the write head
1166 	const char CR = 0x0d;
1167 	const char LF = 0x0a;
1168 
1169 	buf[length] = 0;
1170 	while( *p ) {
1171 		assert( p < (buf+length) );
1172 		assert( q <= (buf+length) );
1173 		assert( q <= p );
1174 
1175 		if ( *p == CR ) {
1176 			*q++ = LF;
1177 			p++;
1178 			if ( *p == LF ) {		// check for CR+LF (and skip LF)
1179 				p++;
1180 			}
1181 		}
1182 		else {
1183 			*q++ = *p++;
1184 		}
1185 	}
1186 	assert( q <= (buf+length) );
1187 	*q = 0;
1188 
1189 	Parse( buf, 0, encoding );
1190 
1191 	delete [] buf;
1192 	return !Error();
1193 }
1194 
1195 
1196 #ifdef ZLIB_H
LoadFile(gzFile file,TiXmlEncoding encoding)1197 bool TiXmlDocument::LoadFile(gzFile file, TiXmlEncoding encoding )
1198 {
1199 
1200 	char *buf = NULL;
1201 	size_t length = 0;
1202 
1203 	// file is loaded in hdr->AS.Header;
1204 	size_t buflen = 1l<<18;
1205 	while (!gzeof(file)) {
1206 		buf = (char*)realloc(buf, buflen);
1207 	    	length += gzread(file, buf+length, buflen-length-1);
1208 	    	buflen *= 2;
1209 	}
1210 	buf[length] = 0;
1211     	buf = (char*)realloc(buf,length+1);
1212 
1213 #ifdef _ICONV_H
1214 	// convert utf-16 to utf-8 if needed
1215 
1216 	const char XML_UTF16LE[] = "\xff\xfe<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0\"\0001\0.\0000\0\"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0\"\0U\0T\0F\0-\0001\0006\0\"\0?\0>\0";
1217 	if (!memcmp(buf, XML_UTF16LE, sizeof(XML_UTF16LE)-1 ) ) {
1218 		char *buf2 = (char*)malloc(length);
1219 		size_t outlen = length;
1220 
1221 		char *inbuf = buf;
1222 		char *outbuf = buf2;
1223 		iconv_t CD = iconv_open ("UTF-8","UTF-16LE");
1224 		size_t iconv_res = iconv (CD, &inbuf, &length, &outbuf, &outlen);
1225 		iconv_close (CD);
1226 
1227 		if (iconv_res != (size_t)(-1)) {
1228 			free(buf);
1229 			outbuf[0] = 0;
1230 			buf = buf2;
1231 			length = strlen(buf);
1232 		}
1233 		else {
1234 			free(buf2);
1235 			fprintf(stderr,"SOPEN_HL7aECG: attempt to convert UTF-16 to UTF-8 failed\n");
1236 		}
1237 	}
1238 #endif
1239 
1240 
1241 	// Process the buffer in place to normalize new lines. (See comment above.)
1242 	// Copies from the 'p' to 'q' pointer, where p can advance faster if
1243 	// a newline-carriage return is hit.
1244 	//
1245 	// Wikipedia:
1246 	// Systems based on ASCII or a compatible character set use either LF  (Line feed, '\n', 0x0A, 10 in decimal) or
1247 	// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
1248 	//		* LF:    Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
1249     //		* CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
1250     //		* CR:    Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
1251 
1252 	const char* p = buf;	// the read head
1253 	char* q = buf;			// the write head
1254 	const char CR = 0x0d;
1255 	const char LF = 0x0a;
1256 
1257 	while( *p ) {
1258 		assert( p < (buf+length) );
1259 		assert( q <= (buf+length) );
1260 		assert( q <= p );
1261 
1262 		if ( *p == CR ) {
1263 			*q++ = LF;
1264 			p++;
1265 			if ( *p == LF ) {		// check for CR+LF (and skip LF)
1266 				p++;
1267 			}
1268 		}
1269 		else {
1270 			*q++ = *p++;
1271 		}
1272 	}
1273 	assert( q <= (buf+length) );
1274 	*q = 0;
1275 
1276 	Parse( buf, 0, encoding );
1277 
1278 	delete [] buf;
1279 	return !Error();
1280 }
1281 #endif
1282 
1283 
SaveFile(const char * filename,char compression) const1284 bool TiXmlDocument::SaveFile( const char * filename, char compression ) const
1285 {
1286 	// The old c stuff lives on...
1287 
1288 	if (compression) {
1289 #ifdef ZLIB_H
1290 		gzFile fid = gzopen(filename, "wb" );
1291 		if (fid) {
1292 			bool result = SaveFile(fid);
1293 			gzclose(fid);
1294 			return result;
1295 		}
1296 #else
1297 		fprintf(stdout,"warning: zlib compression not supported\n");
1298 #endif
1299 	}
1300 	else {
1301 		FILE *fid = fopen(filename, "wb" );
1302 		if (fid) {
1303 			bool result = SaveFile(fid);
1304 			fclose(fid);
1305 			return result;
1306 		}
1307 	}
1308 	return false;
1309 }
1310 
1311 
SaveFile(const char * filename) const1312 bool TiXmlDocument::SaveFile( const char * filename ) const
1313 {
1314 	// The old c stuff lives on...
1315 	FILE* fp = TiXmlFOpen( filename, "w" );
1316 	if ( fp )
1317 	{
1318 		bool result = SaveFile( fp );
1319 		fclose( fp );
1320 		return result;
1321 	}
1322 	return false;
1323 }
1324 
1325 
SaveFile(FILE * fp) const1326 bool TiXmlDocument::SaveFile( FILE* fp ) const
1327 {
1328 	if ( useMicrosoftBOM )
1329 	{
1330 		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1331 		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1332 		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1333 
1334 		fputc( TIXML_UTF_LEAD_0, fp );
1335 		fputc( TIXML_UTF_LEAD_1, fp );
1336 		fputc( TIXML_UTF_LEAD_2, fp );
1337 	}
1338 	Print( fp, 0 );
1339 	return (ferror(fp) == 0);
1340 }
1341 
1342 #ifdef ZLIB_H
SaveFile(gzFile fp) const1343 bool TiXmlDocument::SaveFile( gzFile fp ) const
1344 {
1345 	if ( useMicrosoftBOM )
1346 	{
1347 		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1348 		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1349 		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1350 
1351 		gzputc( fp, TIXML_UTF_LEAD_0 );
1352 		gzputc( fp, TIXML_UTF_LEAD_1 );
1353 		gzputc( fp, TIXML_UTF_LEAD_2 );
1354 	}
1355 	gzPrint( fp, 0 );
1356 	int err;
1357 	gzerror(fp,&err);
1358 	return (err!=0);
1359 }
1360 #endif
1361 
1362 
1363 
CopyTo(TiXmlDocument * target) const1364 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1365 {
1366 	TiXmlNode::CopyTo( target );
1367 
1368 	target->error = error;
1369 	target->errorId = errorId;
1370 	target->errorDesc = errorDesc;
1371 	target->tabsize = tabsize;
1372 	target->errorLocation = errorLocation;
1373 	target->useMicrosoftBOM = useMicrosoftBOM;
1374 
1375 	TiXmlNode* node = 0;
1376 	for ( node = firstChild; node; node = node->NextSibling() )
1377 	{
1378 		target->LinkEndChild( node->Clone() );
1379 	}
1380 }
1381 
1382 
Clone() const1383 TiXmlNode* TiXmlDocument::Clone() const
1384 {
1385 	TiXmlDocument* clone = new TiXmlDocument();
1386 	if ( !clone )
1387 		return 0;
1388 
1389 	CopyTo( clone );
1390 	return clone;
1391 }
1392 
1393 
Print(FILE * cfile,int depth) const1394 void TiXmlDocument::Print( FILE* cfile, int depth ) const
1395 {
1396 	assert( cfile );
1397 	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1398 	{
1399 		node->Print( cfile, depth );
1400 		fprintf( cfile, "\n" );
1401 	}
1402 }
1403 
1404 
1405 #ifdef ZLIB_H
gzPrint(gzFile cfile,int depth) const1406 void TiXmlDocument::gzPrint( gzFile cfile, int depth ) const
1407 {
1408   	assert( cfile );
1409  	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1410   	{
1411  		node->gzPrint( cfile, depth );
1412   		gzprintf( cfile, "\n" );
1413   	}
1414 }
1415 #endif
1416 
1417 
Accept(TiXmlVisitor * visitor) const1418 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1419 {
1420 	if ( visitor->VisitEnter( *this ) )
1421 	{
1422 		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1423 		{
1424 			if ( !node->Accept( visitor ) )
1425 				break;
1426 		}
1427 	}
1428 	return visitor->VisitExit( *this );
1429 }
1430 
1431 
Next() const1432 const TiXmlAttribute* TiXmlAttribute::Next() const
1433 {
1434 	// We are using knowledge of the sentinel. The sentinel
1435 	// have a value or name.
1436 	if ( next->value.empty() && next->name.empty() )
1437 		return 0;
1438 	return next;
1439 }
1440 
1441 /*
1442 TiXmlAttribute* TiXmlAttribute::Next()
1443 {
1444 	// We are using knowledge of the sentinel. The sentinel
1445 	// have a value or name.
1446 	if ( next->value.empty() && next->name.empty() )
1447 		return 0;
1448 	return next;
1449 }
1450 */
1451 
Previous() const1452 const TiXmlAttribute* TiXmlAttribute::Previous() const
1453 {
1454 	// We are using knowledge of the sentinel. The sentinel
1455 	// have a value or name.
1456 	if ( prev->value.empty() && prev->name.empty() )
1457 		return 0;
1458 	return prev;
1459 }
1460 
1461 /*
1462 TiXmlAttribute* TiXmlAttribute::Previous()
1463 {
1464 	// We are using knowledge of the sentinel. The sentinel
1465 	// have a value or name.
1466 	if ( prev->value.empty() && prev->name.empty() )
1467 		return 0;
1468 	return prev;
1469 }
1470 */
1471 
Print(FILE * cfile,int,TIXML_STRING * str) const1472 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1473 {
1474 	TIXML_STRING n, v;
1475 
1476 	EncodeString( name, &n );
1477 	EncodeString( value, &v );
1478 
1479 	if (value.find ('\"') == TIXML_STRING::npos) {
1480 		if ( cfile ) {
1481 			fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1482 		}
1483 		if ( str ) {
1484 			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1485 		}
1486 	}
1487 	else {
1488 		if ( cfile ) {
1489 			fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1490 		}
1491 		if ( str ) {
1492 			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1493 		}
1494 	}
1495 }
1496 
1497 #ifdef ZLIB_H
gzPrint(gzFile cfile,int,TIXML_STRING * str) const1498 void TiXmlAttribute::gzPrint( gzFile cfile, int /*depth*/, TIXML_STRING* str ) const
1499 {
1500 	TIXML_STRING n, v;
1501 
1502 	EncodeString( name, &n );
1503 	EncodeString( value, &v );
1504 
1505 	if (value.find ('\"') == TIXML_STRING::npos) {
1506 		if ( cfile ) {
1507 			gzprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1508 		}
1509 		if ( str ) {
1510 			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1511 		}
1512 	}
1513 	else {
1514 		if ( cfile ) {
1515 			gzprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1516 		}
1517 		if ( str ) {
1518 			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1519 		}
1520 	}
1521 }
1522 #endif
1523 
1524 
QueryIntValue(int * ival) const1525 int TiXmlAttribute::QueryIntValue( int* ival ) const
1526 {
1527 	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1528 		return TIXML_SUCCESS;
1529 	return TIXML_WRONG_TYPE;
1530 }
1531 
QueryDoubleValue(double * dval) const1532 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1533 {
1534 	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1535 		return TIXML_SUCCESS;
1536 	return TIXML_WRONG_TYPE;
1537 }
1538 
SetIntValue(int _value)1539 void TiXmlAttribute::SetIntValue( int _value )
1540 {
1541 	char buf [64];
1542 	#if defined(TIXML_SNPRINTF)
1543 		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1544 	#else
1545 		sprintf (buf, "%d", _value);
1546 	#endif
1547 	SetValue (buf);
1548 }
1549 
SetDoubleValue(double _value)1550 void TiXmlAttribute::SetDoubleValue( double _value )
1551 {
1552 	char buf [256];
1553 	#if defined(TIXML_SNPRINTF)
1554 		TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
1555 	#else
1556 		sprintf (buf, "%g", _value);
1557 	#endif
1558 	SetValue (buf);
1559 }
1560 
IntValue() const1561 int TiXmlAttribute::IntValue() const
1562 {
1563 	return atoi (value.c_str ());
1564 }
1565 
DoubleValue() const1566 double  TiXmlAttribute::DoubleValue() const
1567 {
1568 	return atof (value.c_str ());
1569 }
1570 
1571 
TiXmlComment(const TiXmlComment & copy)1572 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
1573 {
1574 	copy.CopyTo( this );
1575 }
1576 
1577 
operator =(const TiXmlComment & base)1578 TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
1579 {
1580 	Clear();
1581 	base.CopyTo( this );
1582 	return *this;
1583 }
1584 
1585 
Print(FILE * cfile,int depth) const1586 void TiXmlComment::Print( FILE* cfile, int depth ) const
1587 {
1588 	assert( cfile );
1589 	for ( int i=0; i<depth; i++ )
1590 	{
1591 		fprintf( cfile,  "    " );
1592 	}
1593 	fprintf( cfile, "<!--%s-->", value.c_str() );
1594 }
1595 
1596 #ifdef ZLIB_H
gzPrint(gzFile cfile,int depth) const1597 void TiXmlComment::gzPrint( gzFile cfile, int depth ) const
1598 {
1599 	assert( cfile );
1600 	for ( int i=0; i<depth; i++ )
1601 	{
1602 		gzprintf( cfile,  "    " );
1603 	}
1604 	gzprintf( cfile, "<!--%s-->", value.c_str() );
1605 }
1606 #endif
1607 
CopyTo(TiXmlComment * target) const1608 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1609 {
1610 	TiXmlNode::CopyTo( target );
1611 }
1612 
1613 
Accept(TiXmlVisitor * visitor) const1614 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1615 {
1616 	return visitor->Visit( *this );
1617 }
1618 
1619 
Clone() const1620 TiXmlNode* TiXmlComment::Clone() const
1621 {
1622 	TiXmlComment* clone = new TiXmlComment();
1623 
1624 	if ( !clone )
1625 		return 0;
1626 
1627 	CopyTo( clone );
1628 	return clone;
1629 }
1630 
1631 
Print(FILE * cfile,int depth) const1632 void TiXmlText::Print( FILE* cfile, int depth ) const
1633 {
1634 	assert( cfile );
1635 	if ( cdata )
1636 	{
1637 		int i;
1638 		fprintf( cfile, "\n" );
1639 		for ( i=0; i<depth; i++ ) {
1640 			fprintf( cfile, "    " );
1641 		}
1642 		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
1643 	}
1644 	else
1645 	{
1646 		TIXML_STRING buffer;
1647 		EncodeString( value, &buffer );
1648 		fprintf( cfile, "%s", buffer.c_str() );
1649 	}
1650 }
1651 
1652 #ifdef ZLIB_H
gzPrint(gzFile cfile,int depth) const1653 void TiXmlText::gzPrint( gzFile cfile, int depth ) const
1654 {
1655 	assert( cfile );
1656 	if ( cdata )
1657 	{
1658 		int i;
1659 		gzprintf( cfile, "\n" );
1660 		for ( i=0; i<depth; i++ ) {
1661 			gzprintf( cfile, "    " );
1662 		}
1663 		gzprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
1664 	}
1665 	else
1666 	{
1667 		TIXML_STRING buffer;
1668 		EncodeString( value, &buffer );
1669 		gzprintf( cfile, "%s", buffer.c_str() );
1670 	}
1671 }
1672 #endif
1673 
1674 
CopyTo(TiXmlText * target) const1675 void TiXmlText::CopyTo( TiXmlText* target ) const
1676 {
1677 	TiXmlNode::CopyTo( target );
1678 	target->cdata = cdata;
1679 }
1680 
1681 
Accept(TiXmlVisitor * visitor) const1682 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1683 {
1684 	return visitor->Visit( *this );
1685 }
1686 
1687 
Clone() const1688 TiXmlNode* TiXmlText::Clone() const
1689 {
1690 	TiXmlText* clone = 0;
1691 	clone = new TiXmlText( "" );
1692 
1693 	if ( !clone )
1694 		return 0;
1695 
1696 	CopyTo( clone );
1697 	return clone;
1698 }
1699 
1700 
TiXmlDeclaration(const char * _version,const char * _encoding,const char * _standalone)1701 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1702 									const char * _encoding,
1703 									const char * _standalone )
1704 	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1705 {
1706 	version = _version;
1707 	encoding = _encoding;
1708 	standalone = _standalone;
1709 }
1710 
1711 
1712 #ifdef TIXML_USE_STL
TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)1713 TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
1714 									const std::string& _encoding,
1715 									const std::string& _standalone )
1716 	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1717 {
1718 	version = _version;
1719 	encoding = _encoding;
1720 	standalone = _standalone;
1721 }
1722 #endif
1723 
1724 
TiXmlDeclaration(const TiXmlDeclaration & copy)1725 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1726 	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1727 {
1728 	copy.CopyTo( this );
1729 }
1730 
1731 
operator =(const TiXmlDeclaration & copy)1732 TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1733 {
1734 	Clear();
1735 	copy.CopyTo( this );
1736 	return *this;
1737 }
1738 
1739 
Print(FILE * cfile,int,TIXML_STRING * str) const1740 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1741 {
1742 	if ( cfile ) fprintf( cfile, "<?xml " );
1743 	if ( str )	 (*str) += "<?xml ";
1744 
1745 	if ( !version.empty() ) {
1746 		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1747 		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1748 	}
1749 	if ( !encoding.empty() ) {
1750 		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1751 		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1752 	}
1753 	if ( !standalone.empty() ) {
1754 		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1755 		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1756 	}
1757 	if ( cfile ) fprintf( cfile, "?>" );
1758 	if ( str )	 (*str) += "?>";
1759 }
1760 
1761 #ifdef ZLIB_H
gzPrint(gzFile cfile,int,TIXML_STRING * str) const1762 void TiXmlDeclaration::gzPrint( gzFile cfile, int /*depth*/, TIXML_STRING* str ) const
1763 {
1764 	if ( cfile ) gzprintf( cfile, "<?xml " );
1765 	if ( str )	 (*str) += "<?xml ";
1766 
1767 	if ( !version.empty() ) {
1768 		if ( cfile ) gzprintf (cfile, "version=\"%s\" ", version.c_str ());
1769 		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1770 	}
1771 	if ( !encoding.empty() ) {
1772 		if ( cfile ) gzprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1773 		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1774 	}
1775 	if ( !standalone.empty() ) {
1776 		if ( cfile ) gzprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1777 		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1778 	}
1779 	if ( cfile ) gzprintf( cfile, "?>" );
1780 	if ( str )	 (*str) += "?>";
1781 }
1782 #endif
1783 
1784 
CopyTo(TiXmlDeclaration * target) const1785 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1786 {
1787 	TiXmlNode::CopyTo( target );
1788 
1789 	target->version = version;
1790 	target->encoding = encoding;
1791 	target->standalone = standalone;
1792 }
1793 
1794 
Accept(TiXmlVisitor * visitor) const1795 bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1796 {
1797 	return visitor->Visit( *this );
1798 }
1799 
1800 
Clone() const1801 TiXmlNode* TiXmlDeclaration::Clone() const
1802 {
1803 	TiXmlDeclaration* clone = new TiXmlDeclaration();
1804 
1805 	if ( !clone )
1806 		return 0;
1807 
1808 	CopyTo( clone );
1809 	return clone;
1810 }
1811 
1812 
Print(FILE * cfile,int depth) const1813 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1814 {
1815 	for ( int i=0; i<depth; i++ )
1816 		fprintf( cfile, "    " );
1817 	fprintf( cfile, "<%s>", value.c_str() );
1818 }
1819 
1820 #ifdef ZLIB_H
gzPrint(gzFile cfile,int depth) const1821 void TiXmlUnknown::gzPrint( gzFile cfile, int depth ) const
1822 {
1823 	for ( int i=0; i<depth; i++ )
1824 		gzprintf( cfile, "    " );
1825 	gzprintf( cfile, "<%s>", value.c_str() );
1826 }
1827 #endif
1828 
CopyTo(TiXmlUnknown * target) const1829 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1830 {
1831 	TiXmlNode::CopyTo( target );
1832 }
1833 
1834 
Accept(TiXmlVisitor * visitor) const1835 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1836 {
1837 	return visitor->Visit( *this );
1838 }
1839 
1840 
Clone() const1841 TiXmlNode* TiXmlUnknown::Clone() const
1842 {
1843 	TiXmlUnknown* clone = new TiXmlUnknown();
1844 
1845 	if ( !clone )
1846 		return 0;
1847 
1848 	CopyTo( clone );
1849 	return clone;
1850 }
1851 
1852 
TiXmlAttributeSet()1853 TiXmlAttributeSet::TiXmlAttributeSet()
1854 {
1855 	sentinel.next = &sentinel;
1856 	sentinel.prev = &sentinel;
1857 }
1858 
1859 
~TiXmlAttributeSet()1860 TiXmlAttributeSet::~TiXmlAttributeSet()
1861 {
1862 	assert( sentinel.next == &sentinel );
1863 	assert( sentinel.prev == &sentinel );
1864 }
1865 
1866 
Add(TiXmlAttribute * addMe)1867 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1868 {
1869     #ifdef TIXML_USE_STL
1870 	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
1871 	#else
1872 	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
1873 	#endif
1874 
1875 	addMe->next = &sentinel;
1876 	addMe->prev = sentinel.prev;
1877 
1878 	sentinel.prev->next = addMe;
1879 	sentinel.prev      = addMe;
1880 }
1881 
Remove(TiXmlAttribute * removeMe)1882 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1883 {
1884 	TiXmlAttribute* node;
1885 
1886 	for( node = sentinel.next; node != &sentinel; node = node->next )
1887 	{
1888 		if ( node == removeMe )
1889 		{
1890 			node->prev->next = node->next;
1891 			node->next->prev = node->prev;
1892 			node->next = 0;
1893 			node->prev = 0;
1894 			return;
1895 		}
1896 	}
1897 	assert( 0 );		// we tried to remove a non-linked attribute.
1898 }
1899 
1900 
1901 #ifdef TIXML_USE_STL
Find(const std::string & name) const1902 TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1903 {
1904 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1905 	{
1906 		if ( node->name == name )
1907 			return node;
1908 	}
1909 	return 0;
1910 }
1911 
FindOrCreate(const std::string & _name)1912 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
1913 {
1914 	TiXmlAttribute* attrib = Find( _name );
1915 	if ( !attrib ) {
1916 		attrib = new TiXmlAttribute();
1917 		Add( attrib );
1918 		attrib->SetName( _name );
1919 	}
1920 	return attrib;
1921 }
1922 #endif
1923 
1924 
Find(const char * name) const1925 TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1926 {
1927 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1928 	{
1929 		if ( strcmp( node->name.c_str(), name ) == 0 )
1930 			return node;
1931 	}
1932 	return 0;
1933 }
1934 
1935 
FindOrCreate(const char * _name)1936 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
1937 {
1938 	TiXmlAttribute* attrib = Find( _name );
1939 	if ( !attrib ) {
1940 		attrib = new TiXmlAttribute();
1941 		Add( attrib );
1942 		attrib->SetName( _name );
1943 	}
1944 	return attrib;
1945 }
1946 
1947 
1948 #ifdef TIXML_USE_STL
operator >>(std::istream & in,TiXmlNode & base)1949 std::istream& operator>> (std::istream & in, TiXmlNode & base)
1950 {
1951 	TIXML_STRING tag;
1952 	tag.reserve( 8 * 1000 );
1953 	base.StreamIn( &in, &tag );
1954 
1955 	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1956 	return in;
1957 }
1958 #endif
1959 
1960 
1961 #ifdef TIXML_USE_STL
operator <<(std::ostream & out,const TiXmlNode & base)1962 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1963 {
1964 	TiXmlPrinter printer;
1965 	printer.SetStreamPrinting();
1966 	base.Accept( &printer );
1967 	out << printer.Str();
1968 
1969 	return out;
1970 }
1971 
1972 
operator <<(std::string & out,const TiXmlNode & base)1973 std::string& operator<< (std::string& out, const TiXmlNode& base )
1974 {
1975 	TiXmlPrinter printer;
1976 	printer.SetStreamPrinting();
1977 	base.Accept( &printer );
1978 	out.append( printer.Str() );
1979 
1980 	return out;
1981 }
1982 #endif
1983 
1984 
FirstChild() const1985 TiXmlHandle TiXmlHandle::FirstChild() const
1986 {
1987 	if ( node )
1988 	{
1989 		TiXmlNode* child = node->FirstChild();
1990 		if ( child )
1991 			return TiXmlHandle( child );
1992 	}
1993 	return TiXmlHandle( 0 );
1994 }
1995 
1996 
FirstChild(const char * value) const1997 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1998 {
1999 	if ( node )
2000 	{
2001 		TiXmlNode* child = node->FirstChild( value );
2002 		if ( child )
2003 			return TiXmlHandle( child );
2004 	}
2005 	return TiXmlHandle( 0 );
2006 }
2007 
2008 
FirstChildElement() const2009 TiXmlHandle TiXmlHandle::FirstChildElement() const
2010 {
2011 	if ( node )
2012 	{
2013 		TiXmlElement* child = node->FirstChildElement();
2014 		if ( child )
2015 			return TiXmlHandle( child );
2016 	}
2017 	return TiXmlHandle( 0 );
2018 }
2019 
2020 
FirstChildElement(const char * value) const2021 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
2022 {
2023 	if ( node )
2024 	{
2025 		TiXmlElement* child = node->FirstChildElement( value );
2026 		if ( child )
2027 			return TiXmlHandle( child );
2028 	}
2029 	return TiXmlHandle( 0 );
2030 }
2031 
2032 
Child(int count) const2033 TiXmlHandle TiXmlHandle::Child( int count ) const
2034 {
2035 	if ( node )
2036 	{
2037 		int i;
2038 		TiXmlNode* child = node->FirstChild();
2039 		for (	i=0;
2040 				child && i<count;
2041 				child = child->NextSibling(), ++i )
2042 		{
2043 			// nothing
2044 		}
2045 		if ( child )
2046 			return TiXmlHandle( child );
2047 	}
2048 	return TiXmlHandle( 0 );
2049 }
2050 
2051 
Child(const char * value,int count) const2052 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
2053 {
2054 	if ( node )
2055 	{
2056 		int i;
2057 		TiXmlNode* child = node->FirstChild( value );
2058 		for (	i=0;
2059 				child && i<count;
2060 				child = child->NextSibling( value ), ++i )
2061 		{
2062 			// nothing
2063 		}
2064 		if ( child )
2065 			return TiXmlHandle( child );
2066 	}
2067 	return TiXmlHandle( 0 );
2068 }
2069 
2070 
ChildElement(int count) const2071 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
2072 {
2073 	if ( node )
2074 	{
2075 		int i;
2076 		TiXmlElement* child = node->FirstChildElement();
2077 		for (	i=0;
2078 				child && i<count;
2079 				child = child->NextSiblingElement(), ++i )
2080 		{
2081 			// nothing
2082 		}
2083 		if ( child )
2084 			return TiXmlHandle( child );
2085 	}
2086 	return TiXmlHandle( 0 );
2087 }
2088 
2089 
ChildElement(const char * value,int count) const2090 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
2091 {
2092 	if ( node )
2093 	{
2094 		int i;
2095 		TiXmlElement* child = node->FirstChildElement( value );
2096 		for (	i=0;
2097 				child && i<count;
2098 				child = child->NextSiblingElement( value ), ++i )
2099 		{
2100 			// nothing
2101 		}
2102 		if ( child )
2103 			return TiXmlHandle( child );
2104 	}
2105 	return TiXmlHandle( 0 );
2106 }
2107 
2108 
VisitEnter(const TiXmlDocument &)2109 bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
2110 {
2111 	return true;
2112 }
2113 
VisitExit(const TiXmlDocument &)2114 bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
2115 {
2116 	return true;
2117 }
2118 
VisitEnter(const TiXmlElement & element,const TiXmlAttribute * firstAttribute)2119 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
2120 {
2121 	DoIndent();
2122 	buffer += "<";
2123 	buffer += element.Value();
2124 
2125 	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
2126 	{
2127 		buffer += " ";
2128 		attrib->Print( 0, 0, &buffer );
2129 	}
2130 
2131 	if ( !element.FirstChild() )
2132 	{
2133 		buffer += " />";
2134 		DoLineBreak();
2135 	}
2136 	else
2137 	{
2138 		buffer += ">";
2139 		if (    element.FirstChild()->ToText()
2140 			  && element.LastChild() == element.FirstChild()
2141 			  && element.FirstChild()->ToText()->CDATA() == false )
2142 		{
2143 			simpleTextPrint = true;
2144 			// no DoLineBreak()!
2145 		}
2146 		else
2147 		{
2148 			DoLineBreak();
2149 		}
2150 	}
2151 	++depth;
2152 	return true;
2153 }
2154 
2155 
VisitExit(const TiXmlElement & element)2156 bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
2157 {
2158 	--depth;
2159 	if ( !element.FirstChild() )
2160 	{
2161 		// nothing.
2162 	}
2163 	else
2164 	{
2165 		if ( simpleTextPrint )
2166 		{
2167 			simpleTextPrint = false;
2168 		}
2169 		else
2170 		{
2171 			DoIndent();
2172 		}
2173 		buffer += "</";
2174 		buffer += element.Value();
2175 		buffer += ">";
2176 		DoLineBreak();
2177 	}
2178 	return true;
2179 }
2180 
2181 
Visit(const TiXmlText & text)2182 bool TiXmlPrinter::Visit( const TiXmlText& text )
2183 {
2184 	if ( text.CDATA() )
2185 	{
2186 		DoIndent();
2187 		buffer += "<![CDATA[";
2188 		buffer += text.Value();
2189 		buffer += "]]>";
2190 		DoLineBreak();
2191 	}
2192 	else if ( simpleTextPrint )
2193 	{
2194 		TIXML_STRING str;
2195 		TiXmlBase::EncodeString( text.ValueTStr(), &str );
2196 		buffer += str;
2197 	}
2198 	else
2199 	{
2200 		DoIndent();
2201 		TIXML_STRING str;
2202 		TiXmlBase::EncodeString( text.ValueTStr(), &str );
2203 		buffer += str;
2204 		DoLineBreak();
2205 	}
2206 	return true;
2207 }
2208 
2209 
Visit(const TiXmlDeclaration & declaration)2210 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
2211 {
2212 	DoIndent();
2213 	declaration.Print( 0, 0, &buffer );
2214 	DoLineBreak();
2215 	return true;
2216 }
2217 
2218 
Visit(const TiXmlComment & comment)2219 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
2220 {
2221 	DoIndent();
2222 	buffer += "<!--";
2223 	buffer += comment.Value();
2224 	buffer += "-->";
2225 	DoLineBreak();
2226 	return true;
2227 }
2228 
2229 
Visit(const TiXmlUnknown & unknown)2230 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
2231 {
2232 	DoIndent();
2233 	buffer += "<";
2234 	buffer += unknown.Value();
2235 	buffer += ">";
2236 	DoLineBreak();
2237 	return true;
2238 }
2239 
2240