1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original code (2.0 and earlier )copyright (c) 2000-2002 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 #include "tinyxml/tinyxml.h"
26 
27 #include <fstream>
28 #include <iomanip>
29 #include <locale>
30 #include <sstream>
31 
32 bool TiXmlBase::condenseWhiteSpace = true;
33 
PutString(const TIXML_STRING & str,TIXML_OSTREAM * stream)34 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
35 {
36 	TIXML_STRING buffer;
37 	PutString( str, &buffer );
38 	(*stream) << buffer;
39 }
40 
PutString(const TIXML_STRING & str,TIXML_STRING * outString)41 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
42 {
43 	int i=0;
44 
45 	while( i<(int)str.length() )
46 	{
47 		unsigned char c = (unsigned char) str[i];
48 
49 		if (    c == '&'
50 		     && i < ( (int)str.length() - 2 )
51 			 && str[i+1] == '#'
52 			 && str[i+2] == 'x' )
53 		{
54 			// Hexadecimal character reference.
55 			// Pass through unchanged.
56 			// &#xA9;	-- copyright symbol, for example.
57 			//
58 			// The -1 is a bug fix from Rob Laveaux. It keeps
59 			// an overflow from happening if there is no ';'.
60 			// There are actually 2 ways to exit this loop -
61 			// while fails (error case) and break (semicolon found).
62 			// However, there is no mechanism (currently) for
63 			// this function to return an error.
64 			while ( i<(int)str.length()-1 )
65 			{
66 				outString->append( str.c_str() + i, 1 );
67 				++i;
68 				if ( str[i] == ';' )
69 					break;
70 			}
71 		}
72 		else if ( c == '&' )
73 		{
74 			outString->append( entity[0].str, entity[0].strLength );
75 			++i;
76 		}
77 		else if ( c == '<' )
78 		{
79 			outString->append( entity[1].str, entity[1].strLength );
80 			++i;
81 		}
82 		else if ( c == '>' )
83 		{
84 			outString->append( entity[2].str, entity[2].strLength );
85 			++i;
86 		}
87 		else if ( c == '\"' )
88 		{
89 			outString->append( entity[3].str, entity[3].strLength );
90 			++i;
91 		}
92 		else if ( c == '\'' )
93 		{
94 			outString->append( entity[4].str, entity[4].strLength );
95 			++i;
96 		}
97 		else if ( c < 32 )
98 		{
99 			// Easy pass at non-alpha/numeric/symbol
100 			// Below 32 is symbolic.
101 			char buf[ 32 ];
102 			sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
103 			//*ME:	warning C4267: convert 'size_t' to 'int'
104 			//*ME:	Int-Cast to make compiler happy ...
105 			outString->append( buf, (int)strlen( buf ) );
106 			++i;
107 		}
108 		else
109 		{
110 			//char realc = (char) c;
111 			//outString->append( &realc, 1 );
112 			*outString += (char) c;	// somewhat more efficient function call.
113 			++i;
114 		}
115 	}
116 }
117 
118 
119 // <-- Strange class for a bug fix. Search for STL_STRING_BUG
StringToBuffer(const TIXML_STRING & str)120 TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
121 {
122 	buffer = new char[ str.length()+1 ];
123 	if ( buffer )
124 	{
125 		strcpy( buffer, str.c_str() );
126 	}
127 }
128 
129 
~StringToBuffer()130 TiXmlBase::StringToBuffer::~StringToBuffer()
131 {
132 	delete [] buffer;
133 }
134 // End strange bug fix. -->
135 
136 
TiXmlNode(NodeType _type)137 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
138 {
139 	parent = 0;
140 	type = _type;
141 	firstChild = 0;
142 	lastChild = 0;
143 	prev = 0;
144 	next = 0;
145 }
146 
147 
~TiXmlNode()148 TiXmlNode::~TiXmlNode()
149 {
150 	TiXmlNode* node = firstChild;
151 	TiXmlNode* temp = 0;
152 
153 	while ( node )
154 	{
155 		temp = node;
156 		node = node->next;
157 		delete temp;
158 	}
159 }
160 
161 
CopyTo(TiXmlNode * target) const162 void TiXmlNode::CopyTo( TiXmlNode* target ) const
163 {
164 	target->SetValue (value.c_str() );
165 	target->userData = userData;
166 }
167 
168 
Clear()169 void TiXmlNode::Clear()
170 {
171 	TiXmlNode* node = firstChild;
172 	TiXmlNode* temp = 0;
173 
174 	while ( node )
175 	{
176 		temp = node;
177 		node = node->next;
178 		delete temp;
179 	}
180 
181 	firstChild = 0;
182 	lastChild = 0;
183 }
184 
185 
LinkEndChild(TiXmlNode * node)186 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
187 {
188 	node->parent = this;
189 
190 	node->prev = lastChild;
191 	node->next = 0;
192 
193 	if ( lastChild )
194 		lastChild->next = node;
195 	else
196 		firstChild = node;			// it was an empty list.
197 
198 	lastChild = node;
199 	return node;
200 }
201 
202 
InsertEndChild(const TiXmlNode & addThis)203 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
204 {
205 	TiXmlNode* node = addThis.Clone();
206 	if ( !node )
207 		return 0;
208 
209 	return LinkEndChild( node );
210 }
211 
212 
InsertBeforeChild(TiXmlNode * beforeThis,const TiXmlNode & addThis)213 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
214 {
215 	if ( !beforeThis || beforeThis->parent != this )
216 		return 0;
217 
218 	TiXmlNode* node = addThis.Clone();
219 	if ( !node )
220 		return 0;
221 	node->parent = this;
222 
223 	node->next = beforeThis;
224 	node->prev = beforeThis->prev;
225 	if ( beforeThis->prev )
226 	{
227 		beforeThis->prev->next = node;
228 	}
229 	else
230 	{
231 		assert( firstChild == beforeThis );
232 		firstChild = node;
233 	}
234 	beforeThis->prev = node;
235 	return node;
236 }
237 
238 
InsertAfterChild(TiXmlNode * afterThis,const TiXmlNode & addThis)239 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
240 {
241 	if ( !afterThis || afterThis->parent != this )
242 		return 0;
243 
244 	TiXmlNode* node = addThis.Clone();
245 	if ( !node )
246 		return 0;
247 	node->parent = this;
248 
249 	node->prev = afterThis;
250 	node->next = afterThis->next;
251 	if ( afterThis->next )
252 	{
253 		afterThis->next->prev = node;
254 	}
255 	else
256 	{
257 		assert( lastChild == afterThis );
258 		lastChild = node;
259 	}
260 	afterThis->next = node;
261 	return node;
262 }
263 
264 
ReplaceChild(TiXmlNode * replaceThis,const TiXmlNode & withThis)265 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
266 {
267 	if ( replaceThis->parent != this )
268 		return 0;
269 
270 	TiXmlNode* node = withThis.Clone();
271 	if ( !node )
272 		return 0;
273 
274 	node->next = replaceThis->next;
275 	node->prev = replaceThis->prev;
276 
277 	if ( replaceThis->next )
278 		replaceThis->next->prev = node;
279 	else
280 		lastChild = node;
281 
282 	if ( replaceThis->prev )
283 		replaceThis->prev->next = node;
284 	else
285 		firstChild = node;
286 
287 	delete replaceThis;
288 	node->parent = this;
289 	return node;
290 }
291 
292 
RemoveChild(TiXmlNode * removeThis)293 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
294 {
295 	if ( removeThis->parent != this )
296 	{
297 		assert( 0 );
298 		return false;
299 	}
300 
301 	if ( removeThis->next )
302 		removeThis->next->prev = removeThis->prev;
303 	else
304 		lastChild = removeThis->prev;
305 
306 	if ( removeThis->prev )
307 		removeThis->prev->next = removeThis->next;
308 	else
309 		firstChild = removeThis->next;
310 
311 	delete removeThis;
312 	return true;
313 }
314 
FirstChild(const char * _value) const315 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
316 {
317 	const TiXmlNode* node;
318 	for ( node = firstChild; node; node = node->next )
319 	{
320 		if ( node->SValue() == TIXML_STRING( _value ))
321 			return node;
322 	}
323 	return 0;
324 }
325 
326 
FirstChild(const char * _value)327 TiXmlNode* TiXmlNode::FirstChild( const char * _value )
328 {
329 	TiXmlNode* node;
330 	for ( node = firstChild; node; node = node->next )
331 	{
332 		if ( node->SValue() == TIXML_STRING( _value ))
333 			return node;
334 	}
335 	return 0;
336 }
337 
338 
LastChild(const char * _value) const339 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
340 {
341 	const TiXmlNode* node;
342 	for ( node = lastChild; node; node = node->prev )
343 	{
344 		if ( node->SValue() == TIXML_STRING (_value))
345 			return node;
346 	}
347 	return 0;
348 }
349 
LastChild(const char * _value)350 TiXmlNode* TiXmlNode::LastChild( const char * _value )
351 {
352 	TiXmlNode* node;
353 	for ( node = lastChild; node; node = node->prev )
354 	{
355 		if ( node->SValue() == TIXML_STRING (_value))
356 			return node;
357 	}
358 	return 0;
359 }
360 
IterateChildren(TiXmlNode * previous) const361 const TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
362 {
363 	if ( !previous )
364 	{
365 		return FirstChild();
366 	}
367 	else
368 	{
369 		assert( previous->parent == this );
370 		return previous->NextSibling();
371 	}
372 }
373 
IterateChildren(TiXmlNode * previous)374 TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
375 {
376 	if ( !previous )
377 	{
378 		return FirstChild();
379 	}
380 	else
381 	{
382 		assert( previous->parent == this );
383 		return previous->NextSibling();
384 	}
385 }
386 
IterateChildren(const char * val,TiXmlNode * previous) const387 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
388 {
389 	if ( !previous )
390 	{
391 		return FirstChild( val );
392 	}
393 	else
394 	{
395 		assert( previous->parent == this );
396 		return previous->NextSibling( val );
397 	}
398 }
399 
IterateChildren(const char * val,TiXmlNode * previous)400 TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
401 {
402 	if ( !previous )
403 	{
404 		return FirstChild( val );
405 	}
406 	else
407 	{
408 		assert( previous->parent == this );
409 		return previous->NextSibling( val );
410 	}
411 }
412 
NextSibling(const char * _value) const413 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
414 {
415 	const TiXmlNode* node;
416 	for ( node = next; node; node = node->next )
417 	{
418 		if ( node->SValue() == TIXML_STRING (_value))
419 			return node;
420 	}
421 	return 0;
422 }
423 
NextSibling(const char * _value)424 TiXmlNode* TiXmlNode::NextSibling( const char * _value )
425 {
426 	TiXmlNode* node;
427 	for ( node = next; node; node = node->next )
428 	{
429 		if ( node->SValue() == TIXML_STRING (_value))
430 			return node;
431 	}
432 	return 0;
433 }
434 
PreviousSibling(const char * _value) const435 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
436 {
437 	const TiXmlNode* node;
438 	for ( node = prev; node; node = node->prev )
439 	{
440 		if ( node->SValue() == TIXML_STRING (_value))
441 			return node;
442 	}
443 	return 0;
444 }
445 
PreviousSibling(const char * _value)446 TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
447 {
448 	TiXmlNode* node;
449 	for ( node = prev; node; node = node->prev )
450 	{
451 		if ( node->SValue() == TIXML_STRING (_value))
452 			return node;
453 	}
454 	return 0;
455 }
456 
RemoveAttribute(const char * name)457 void TiXmlElement::RemoveAttribute( const char * name )
458 {
459 	TiXmlAttribute* node = attributeSet.Find( name );
460 	if ( node )
461 	{
462 		attributeSet.Remove( node );
463 		delete node;
464 	}
465 }
466 
FirstChildElement() const467 const TiXmlElement* TiXmlNode::FirstChildElement() const
468 {
469 	const TiXmlNode* node;
470 
471 	for (	node = FirstChild();
472 			node;
473 			node = node->NextSibling() )
474 	{
475 		if ( node->ToElement() )
476 			return node->ToElement();
477 	}
478 	return 0;
479 }
480 
FirstChildElement()481 TiXmlElement* TiXmlNode::FirstChildElement()
482 {
483 	TiXmlNode* node;
484 
485 	for (	node = FirstChild();
486 			node;
487 			node = node->NextSibling() )
488 	{
489 		if ( node->ToElement() )
490 			return node->ToElement();
491 	}
492 	return 0;
493 }
494 
FirstChildElement(const char * _value) const495 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
496 {
497 	const TiXmlNode* node;
498 
499 	for (	node = FirstChild( _value );
500 			node;
501 			node = node->NextSibling( _value ) )
502 	{
503 		if ( node->ToElement() )
504 			return node->ToElement();
505 	}
506 	return 0;
507 }
508 
FirstChildElement(const char * _value)509 TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
510 {
511 	TiXmlNode* node;
512 
513 	for (	node = FirstChild( _value );
514 			node;
515 			node = node->NextSibling( _value ) )
516 	{
517 		if ( node->ToElement() )
518 			return node->ToElement();
519 	}
520 	return 0;
521 }
522 
NextSiblingElement() const523 const TiXmlElement* TiXmlNode::NextSiblingElement() const
524 {
525 	const TiXmlNode* node;
526 
527 	for (	node = NextSibling();
528 	node;
529 	node = node->NextSibling() )
530 	{
531 		if ( node->ToElement() )
532 			return node->ToElement();
533 	}
534 	return 0;
535 }
536 
NextSiblingElement()537 TiXmlElement* TiXmlNode::NextSiblingElement()
538 {
539 	TiXmlNode* node;
540 
541 	for (	node = NextSibling();
542 	node;
543 	node = node->NextSibling() )
544 	{
545 		if ( node->ToElement() )
546 			return node->ToElement();
547 	}
548 	return 0;
549 }
550 
NextSiblingElement(const char * _value) const551 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
552 {
553 	const TiXmlNode* node;
554 
555 	for (	node = NextSibling( _value );
556 	node;
557 	node = node->NextSibling( _value ) )
558 	{
559 		if ( node->ToElement() )
560 			return node->ToElement();
561 	}
562 	return 0;
563 }
564 
NextSiblingElement(const char * _value)565 TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
566 {
567 	TiXmlNode* node;
568 
569 	for (	node = NextSibling( _value );
570 	node;
571 	node = node->NextSibling( _value ) )
572 	{
573 		if ( node->ToElement() )
574 			return node->ToElement();
575 	}
576 	return 0;
577 }
578 
579 
GetDocument() const580 const TiXmlDocument* TiXmlNode::GetDocument() const
581 {
582 	const TiXmlNode* node;
583 
584 	for( node = this; node; node = node->parent )
585 	{
586 		if ( node->ToDocument() )
587 			return node->ToDocument();
588 	}
589 	return 0;
590 }
591 
GetDocument()592 TiXmlDocument* TiXmlNode::GetDocument()
593 {
594 	TiXmlNode* node;
595 
596 	for( node = this; node; node = node->parent )
597 	{
598 		if ( node->ToDocument() )
599 			return node->ToDocument();
600 	}
601 	return 0;
602 }
603 
TiXmlElement(const char * _value)604 TiXmlElement::TiXmlElement (const char * _value)
605 	: TiXmlNode( TiXmlNode::ELEMENT )
606 {
607 	firstChild = lastChild = 0;
608 	value = _value;
609 }
610 
611 
612 #ifdef TIXML_USE_STL
TiXmlElement(const std::string & _value)613 TiXmlElement::TiXmlElement( const std::string& _value )
614 	: TiXmlNode( TiXmlNode::ELEMENT )
615 {
616 	firstChild = lastChild = 0;
617 	value = _value;
618 }
619 #endif
620 
621 
TiXmlElement(const TiXmlElement & copy)622 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
623 	: TiXmlNode( TiXmlNode::ELEMENT )
624 {
625 	firstChild = lastChild = 0;
626 	copy.CopyTo( this );
627 }
628 
629 
operator =(const TiXmlElement & base)630 void TiXmlElement::operator=( const TiXmlElement& base )
631 {
632 	ClearThis();
633 	base.CopyTo( this );
634 }
635 
636 
~TiXmlElement()637 TiXmlElement::~TiXmlElement()
638 {
639 	ClearThis();
640 }
641 
642 
ClearThis()643 void TiXmlElement::ClearThis()
644 {
645 	Clear();
646 	while( attributeSet.First() )
647 	{
648 		TiXmlAttribute* node = attributeSet.First();
649 		attributeSet.Remove( node );
650 		delete node;
651 	}
652 }
653 
654 
Attribute(const char * name) const655 const char * TiXmlElement::Attribute( const char * name ) const
656 {
657 	const TiXmlAttribute* node = attributeSet.Find( name );
658 
659 	if ( node )
660 		return node->Value();
661 
662 	return 0;
663 }
664 
665 
Attribute(const char * name,int * i) const666 const char * TiXmlElement::Attribute( const char * name, int* i ) const
667 {
668 	const char * s = Attribute( name );
669 	if ( i )
670 	{
671 		if ( s )
672 			*i = atoi( s );
673 		else
674 			*i = 0;
675 	}
676 	return s;
677 }
678 
679 
Attribute(const char * name,double * d) const680 const char * TiXmlElement::Attribute( const char * name, double* d ) const
681 {
682 	const char * s = Attribute( name );
683 	if ( d )
684 	{
685 		if ( s )
686 			*d = atof( s );
687 		else
688 			*d = 0;
689 	}
690 	return s;
691 }
692 
693 
QueryIntAttribute(const char * name,int * ival) const694 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
695 {
696 	const TiXmlAttribute* node = attributeSet.Find( name );
697 	if ( !node )
698 		return TIXML_NO_ATTRIBUTE;
699 
700 	return node->QueryIntValue( ival );
701 }
702 
703 
QueryDoubleAttribute(const char * name,double * dval) const704 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
705 {
706 	const TiXmlAttribute* node = attributeSet.Find( name );
707 	if ( !node )
708 		return TIXML_NO_ATTRIBUTE;
709 
710 	return node->QueryDoubleValue( dval );
711 }
712 
713 
SetAttribute(const char * name,int val)714 void TiXmlElement::SetAttribute( const char * name, int val )
715 {
716 	char buf[64];
717 	sprintf( buf, "%d", val );
718 	SetAttribute( name, buf );
719 }
720 
721 
SetDoubleAttribute(const char * name,double val)722 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
723 {
724 	char buf[64];
725 	std::stringstream sst;
726 	sst.imbue(std::locale::classic());
727 	sst << std::fixed;
728 	sst << std::showpoint;
729 	sst << std::setprecision(6);
730 	sst << val;
731 	strncpy( buf, sst.str().c_str(), 63 );
732 	SetAttribute( name, buf);
733 }
734 
735 
SetAttribute(const char * name,const char * _value)736 void TiXmlElement::SetAttribute( const char * name, const char * _value )
737 {
738 	TiXmlAttribute* node = attributeSet.Find( name );
739 	if ( node )
740 	{
741 		node->SetValue( _value );
742 		return;
743 	}
744 
745 	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
746 	if ( attrib )
747 	{
748 		attributeSet.Add( attrib );
749 	}
750 	else
751 	{
752 		TiXmlDocument* document = GetDocument();
753 		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
754 	}
755 }
756 
Print(TIXML_OSTREAM & cfile,int depth) const757 void TiXmlElement::Print( TIXML_OSTREAM& cfile, int depth ) const
758 {
759 	int i;
760 	for ( i=0; i<depth; i++ )
761 	{
762 		cfile << "    ";
763 	}
764 
765 	cfile << '<' << value;
766 
767 	const TiXmlAttribute* attrib;
768 	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
769 	{
770 		cfile << ' ';
771 		attrib->Print( cfile, depth );
772 	}
773 
774 	// There are 3 different formatting approaches:
775 	// 1) An element without children is printed as a <foo /> node
776 	// 2) An element with only a text child is printed as <foo> text </foo>
777 	// 3) An element with children is printed on multiple lines.
778 	TiXmlNode* node;
779 	if ( !firstChild )
780 	{
781 		cfile << " />";
782 	}
783 	else if ( firstChild == lastChild && firstChild->ToText() )
784 	{
785 		cfile << '>';
786 		firstChild->Print( cfile, depth + 1 );
787 		cfile << "</" << value << '>';
788 	}
789 	else
790 	{
791 		cfile << '>';
792 
793 		for ( node = firstChild; node; node=node->NextSibling() )
794 		{
795 			if ( !node->ToText() )
796 			{
797 				cfile << '\n';
798 			}
799 			node->Print( cfile, depth+1 );
800 		}
801 		cfile << '\n';
802 		for( i=0; i<depth; ++i )
803 			cfile << "    ";
804 		cfile << "</" << value << '>';
805 	}
806 }
807 
StreamOut(TIXML_OSTREAM * stream) const808 void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
809 {
810 	(*stream) << "<" << value;
811 
812 	const TiXmlAttribute* attrib;
813 	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
814 	{
815 		(*stream) << " ";
816 		attrib->StreamOut( stream );
817 	}
818 
819 	// If this node has children, give it a closing tag. Else
820 	// make it an empty tag.
821 	TiXmlNode* node;
822 	if ( firstChild )
823 	{
824 		(*stream) << ">";
825 
826 		for ( node = firstChild; node; node=node->NextSibling() )
827 		{
828 			node->StreamOut( stream );
829 		}
830 		(*stream) << "</" << value << ">";
831 	}
832 	else
833 	{
834 		(*stream) << " />";
835 	}
836 }
837 
838 
CopyTo(TiXmlElement * target) const839 void TiXmlElement::CopyTo( TiXmlElement* target ) const
840 {
841 	// superclass:
842 	TiXmlNode::CopyTo( target );
843 
844 	// Element class:
845 	// Clone the attributes, then clone the children.
846 	const TiXmlAttribute* attribute = 0;
847 	for(	attribute = attributeSet.First();
848 	attribute;
849 	attribute = attribute->Next() )
850 	{
851 		target->SetAttribute( attribute->Name(), attribute->Value() );
852 	}
853 
854 	TiXmlNode* node = 0;
855 	for ( node = firstChild; node; node = node->NextSibling() )
856 	{
857 		target->LinkEndChild( node->Clone() );
858 	}
859 }
860 
861 
Clone() const862 TiXmlNode* TiXmlElement::Clone() const
863 {
864 	TiXmlElement* clone = new TiXmlElement( Value() );
865 	if ( !clone )
866 		return 0;
867 
868 	CopyTo( clone );
869 	return clone;
870 }
871 
872 
TiXmlDocument()873 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
874 {
875 	tabsize = 4;
876 	ClearError();
877 }
878 
TiXmlDocument(const char * documentName)879 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
880 {
881 	tabsize = 4;
882 	value = documentName;
883 	ClearError();
884 }
885 
886 
887 #ifdef TIXML_USE_STL
TiXmlDocument(const std::string & documentName)888 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
889 {
890 	tabsize = 4;
891     value = documentName;
892 	ClearError();
893 }
894 #endif
895 
896 
TiXmlDocument(const TiXmlDocument & copy)897 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
898 {
899 	copy.CopyTo( this );
900 }
901 
902 
operator =(const TiXmlDocument & copy)903 void TiXmlDocument::operator=( const TiXmlDocument& copy )
904 {
905 	Clear();
906 	copy.CopyTo( this );
907 }
908 
909 
LoadFile(TiXmlEncoding encoding)910 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
911 {
912 #ifdef TIXML_USE_STL
913 	return LoadFile(fs::u8path(value), encoding);
914 #else
915 	// See STL_STRING_BUG below.
916 	StringToBuffer buf( value );
917 
918 	if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
919 		return true;
920 
921 	return false;
922 #endif
923 }
924 
925 
SaveFile() const926 bool TiXmlDocument::SaveFile() const
927 {
928 #ifdef TIXML_USE_STL
929 	return SaveFile(fs::u8path(value));
930 #else
931 	// See STL_STRING_BUG below.
932 	StringToBuffer buf( value );
933 
934 	if ( buf.buffer && SaveFile( buf.buffer ) )
935 		return true;
936 
937 	return false;
938 #endif
939 }
940 
941 #ifndef TIXML_USE_STL
LoadFile(const char * filename,TiXmlEncoding encoding)942 bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
943 {
944 	// Delete the existing data:
945 	Clear();
946 	location.Clear();
947 
948 	// There was a really terrifying little bug here. The code:
949 	//		value = filename
950 	// in the STL case, cause the assignment method of the std::string to
951 	// be called. What is strange, is that the std::string had the same
952 	// address as it's c_str() method, and so bad things happen. Looks
953 	// like a bug in the Microsoft STL implementation.
954 	// See STL_STRING_BUG above.
955 	// Fixed with the StringToBuffer class.
956 	value = filename;
957 
958 	FILE* file = fopen( value.c_str (), "r" );
959 
960 	if ( file )
961 	{
962 		// Get the file size, so we can pre-allocate the string. HUGE speed impact.
963 		long length = 0;
964 		fseek( file, 0, SEEK_END );
965 		length = ftell( file );
966 		fseek( file, 0, SEEK_SET );
967 
968 		// Strange case, but good to handle up front.
969 		if ( length == 0 )
970 		{
971 			fclose( file );
972 			return false;
973 		}
974 
975 		// If we have a file, assume it is all one big XML file, and read it in.
976 		// The document parser may decide the document ends sooner than the entire file, however.
977 		TIXML_STRING data;
978 		data.reserve( length );
979 
980 		const int BUF_SIZE = 2048;
981 		char buf[BUF_SIZE];
982 
983 		while( fgets( buf, BUF_SIZE, file ) )
984 		{
985 			data += buf;
986 		}
987 		fclose( file );
988 
989 		Parse( data.c_str(), 0, encoding );
990 
991 		if (  Error() )
992             return false;
993         else
994 			return true;
995 	}
996 	SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
997 	return false;
998 }
999 
SaveFile(const char * filename) const1000 bool TiXmlDocument::SaveFile( const char * filename ) const
1001 {
1002 	// The old c stuff lives on...
1003 	FILE* fp = fopen( filename, "w" );
1004 	if ( fp )
1005 	{
1006 		Print( fp, 0 );
1007 		fclose( fp );
1008 		return true;
1009 	}
1010 	return false;
1011 }
1012 
1013 #else // !TIXML_USE_STL
1014 
LoadFile(const fs::path & filename,TiXmlEncoding encoding)1015 bool TiXmlDocument::LoadFile( const fs::path& filename, TiXmlEncoding encoding )
1016 {
1017 	Clear();
1018 	location.Clear();
1019 
1020 	value = filename.u8string();
1021 
1022 	std::error_code ec;
1023 	const auto length = fs::file_size(filename, ec);
1024 	if (ec || length == 0)
1025 		return false;
1026 
1027 	std::unique_ptr<char[]> data;
1028 	{
1029 		std::filebuf file;
1030 		if (file.open(filename, std::ios::binary | std::ios::in))
1031 		{
1032 			data.reset(new char[length + 1]);
1033 			if (file.sgetn(data.get(), length) != length)
1034 				return false;
1035 		}
1036 		else
1037 		{
1038 			SetError(TIXML_ERROR_OPENING_FILE, nullptr, nullptr, TIXML_ENCODING_UNKNOWN);
1039 			return false;
1040 		}
1041 	}
1042 	data[length] = '\0';
1043 	Parse(data.get(), nullptr, encoding);
1044 	return !Error();
1045 }
1046 
SaveFile(const fs::path & filename) const1047 bool TiXmlDocument::SaveFile( const fs::path& filename ) const
1048 {
1049 	if (std::ofstream stream{filename, std::ios::binary | std::ios::out | std::ios::trunc})
1050 	{
1051 		Print(stream, 0);
1052 		return true;
1053 	}
1054 	return false;
1055 }
1056 #endif // TIXML_USE_STL
1057 
CopyTo(TiXmlDocument * target) const1058 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1059 {
1060 	TiXmlNode::CopyTo( target );
1061 
1062 	target->error = error;
1063 	target->errorDesc = errorDesc.c_str ();
1064 
1065 	TiXmlNode* node = 0;
1066 	for ( node = firstChild; node; node = node->NextSibling() )
1067 	{
1068 		target->LinkEndChild( node->Clone() );
1069 	}
1070 }
1071 
1072 
Clone() const1073 TiXmlNode* TiXmlDocument::Clone() const
1074 {
1075 	TiXmlDocument* clone = new TiXmlDocument();
1076 	if ( !clone )
1077 		return 0;
1078 
1079 	CopyTo( clone );
1080 	return clone;
1081 }
1082 
1083 
Print(TIXML_OSTREAM & cfile,int depth) const1084 void TiXmlDocument::Print( TIXML_OSTREAM& cfile, int depth ) const
1085 {
1086 	const TiXmlNode* node;
1087 	for ( node=FirstChild(); node; node=node->NextSibling() )
1088 	{
1089 		node->Print( cfile, depth );
1090 		cfile << '\n';
1091 	}
1092 }
1093 
StreamOut(TIXML_OSTREAM * out) const1094 void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
1095 {
1096 	const TiXmlNode* node;
1097 	for ( node=FirstChild(); node; node=node->NextSibling() )
1098 	{
1099 		node->StreamOut( out );
1100 
1101 		// Special rule for streams: stop after the root element.
1102 		// The stream in code will only read one element, so don't
1103 		// write more than one.
1104 		if ( node->ToElement() )
1105 			break;
1106 	}
1107 }
1108 
1109 
Next() const1110 const TiXmlAttribute* TiXmlAttribute::Next() const
1111 {
1112 	// We are using knowledge of the sentinel. The sentinel
1113 	// have a value or name.
1114 	if ( next->value.empty() && next->name.empty() )
1115 		return 0;
1116 	return next;
1117 }
1118 
Next()1119 TiXmlAttribute* TiXmlAttribute::Next()
1120 {
1121 	// We are using knowledge of the sentinel. The sentinel
1122 	// have a value or name.
1123 	if ( next->value.empty() && next->name.empty() )
1124 		return 0;
1125 	return next;
1126 }
1127 
Previous() const1128 const TiXmlAttribute* TiXmlAttribute::Previous() const
1129 {
1130 	// We are using knowledge of the sentinel. The sentinel
1131 	// have a value or name.
1132 	if ( prev->value.empty() && prev->name.empty() )
1133 		return 0;
1134 	return prev;
1135 }
1136 
Previous()1137 TiXmlAttribute* TiXmlAttribute::Previous()
1138 {
1139 	// We are using knowledge of the sentinel. The sentinel
1140 	// have a value or name.
1141 	if ( prev->value.empty() && prev->name.empty() )
1142 		return 0;
1143 	return prev;
1144 }
1145 
Print(TIXML_OSTREAM & cfile,int) const1146 void TiXmlAttribute::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const
1147 {
1148 	TIXML_STRING n, v;
1149 
1150 	PutString( name, &n );
1151 	PutString( value, &v );
1152 
1153 	if (value.find ('\"') == TIXML_STRING::npos)
1154 		cfile << n << "=\"" << v << '"';
1155 	else
1156 		cfile << n << "='" << v << '\'';
1157 }
1158 
1159 
StreamOut(TIXML_OSTREAM * stream) const1160 void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
1161 {
1162 	if (value.find( '\"' ) != TIXML_STRING::npos)
1163 	{
1164 		PutString( name, stream );
1165 		(*stream) << "=" << "'";
1166 		PutString( value, stream );
1167 		(*stream) << "'";
1168 	}
1169 	else
1170 	{
1171 		PutString( name, stream );
1172 		(*stream) << "=" << "\"";
1173 		PutString( value, stream );
1174 		(*stream) << "\"";
1175 	}
1176 }
1177 
QueryIntValue(int * ival) const1178 int TiXmlAttribute::QueryIntValue( int* ival ) const
1179 {
1180 	if ( sscanf( value.c_str(), "%d", ival ) == 1 )
1181 		return TIXML_SUCCESS;
1182 	return TIXML_WRONG_TYPE;
1183 }
1184 
QueryDoubleValue(double * dval) const1185 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1186 {
1187 	std::stringstream sst;
1188 	sst.imbue(std::locale::classic());
1189 	sst << value.c_str();
1190 	if ( sst >> *dval )
1191 		return TIXML_SUCCESS;
1192 	return TIXML_WRONG_TYPE;
1193 }
1194 
SetIntValue(int _value)1195 void TiXmlAttribute::SetIntValue( int _value )
1196 {
1197 	char buf [64];
1198 	sprintf (buf, "%d", _value);
1199 	SetValue (buf);
1200 }
1201 
SetDoubleValue(double _value)1202 void TiXmlAttribute::SetDoubleValue( double _value )
1203 {
1204 	char buf [64];
1205 	std::stringstream sst;
1206 	sst.imbue(std::locale::classic());
1207 	sst << std::fixed;
1208 	sst << std::showpoint;
1209 	sst << std::setprecision(6);
1210 	sst << _value;
1211 	strncpy( buf, sst.str().c_str(), 63 );
1212 	SetValue (buf);
1213 }
1214 
IntValue() const1215 int TiXmlAttribute::IntValue() const
1216 {
1217 	return atoi (value.c_str ());
1218 }
1219 
DoubleValue() const1220 double  TiXmlAttribute::DoubleValue() const
1221 {
1222 	return atof (value.c_str ());
1223 }
1224 
1225 
TiXmlComment(const TiXmlComment & copy)1226 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1227 {
1228 	copy.CopyTo( this );
1229 }
1230 
1231 
operator =(const TiXmlComment & base)1232 void TiXmlComment::operator=( const TiXmlComment& base )
1233 {
1234 	Clear();
1235 	base.CopyTo( this );
1236 }
1237 
1238 
Print(TIXML_OSTREAM & cfile,int depth) const1239 void TiXmlComment::Print( TIXML_OSTREAM& cfile, int depth ) const
1240 {
1241 	for ( int i=0; i<depth; i++ )
1242 	{
1243 		cfile << "    ";
1244 	}
1245 	cfile << "<!--" << value << "-->";
1246 }
1247 
StreamOut(TIXML_OSTREAM * stream) const1248 void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
1249 {
1250 	(*stream) << "<!--";
1251 	//PutString( value, stream );
1252 	(*stream) << value;
1253 	(*stream) << "-->";
1254 }
1255 
1256 
CopyTo(TiXmlComment * target) const1257 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1258 {
1259 	TiXmlNode::CopyTo( target );
1260 }
1261 
1262 
Clone() const1263 TiXmlNode* TiXmlComment::Clone() const
1264 {
1265 	TiXmlComment* clone = new TiXmlComment();
1266 
1267 	if ( !clone )
1268 		return 0;
1269 
1270 	CopyTo( clone );
1271 	return clone;
1272 }
1273 
1274 
Print(TIXML_OSTREAM & cfile,int) const1275 void TiXmlText::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const
1276 {
1277 	TIXML_STRING buffer;
1278 	PutString( value, &buffer );
1279 	cfile << buffer;
1280 }
1281 
1282 
StreamOut(TIXML_OSTREAM * stream) const1283 void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
1284 {
1285 	PutString( value, stream );
1286 }
1287 
1288 
CopyTo(TiXmlText * target) const1289 void TiXmlText::CopyTo( TiXmlText* target ) const
1290 {
1291 	TiXmlNode::CopyTo( target );
1292 }
1293 
1294 
Clone() const1295 TiXmlNode* TiXmlText::Clone() const
1296 {
1297 	TiXmlText* clone = 0;
1298 	clone = new TiXmlText( "" );
1299 
1300 	if ( !clone )
1301 		return 0;
1302 
1303 	CopyTo( clone );
1304 	return clone;
1305 }
1306 
1307 
TiXmlDeclaration(const char * _version,const char * _encoding,const char * _standalone)1308 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1309 									const char * _encoding,
1310 									const char * _standalone )
1311 	: TiXmlNode( TiXmlNode::DECLARATION )
1312 {
1313 	version = _version;
1314 	encoding = _encoding;
1315 	standalone = _standalone;
1316 }
1317 
1318 
1319 #ifdef TIXML_USE_STL
TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)1320 TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
1321 									const std::string& _encoding,
1322 									const std::string& _standalone )
1323 	: TiXmlNode( TiXmlNode::DECLARATION )
1324 {
1325 	version = _version;
1326 	encoding = _encoding;
1327 	standalone = _standalone;
1328 }
1329 #endif
1330 
1331 
TiXmlDeclaration(const TiXmlDeclaration & copy)1332 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1333 	: TiXmlNode( TiXmlNode::DECLARATION )
1334 {
1335 	copy.CopyTo( this );
1336 }
1337 
1338 
operator =(const TiXmlDeclaration & copy)1339 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1340 {
1341 	Clear();
1342 	copy.CopyTo( this );
1343 }
1344 
1345 
Print(TIXML_OSTREAM & cfile,int) const1346 void TiXmlDeclaration::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const
1347 {
1348 	cfile << "<?xml ";
1349 	if ( !version.empty() )
1350 		cfile << "version=\"" << version << "\" ";
1351 	if ( !encoding.empty() )
1352 		cfile << "encoding=\"" << encoding << "\" ";
1353 	if ( !standalone.empty() )
1354 		cfile << "standalone=\"" << standalone << "\" ";
1355 	cfile << "?>";
1356 }
1357 
StreamOut(TIXML_OSTREAM * stream) const1358 void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
1359 {
1360 	(*stream) << "<?xml ";
1361 
1362 	if ( !version.empty() )
1363 	{
1364 		(*stream) << "version=\"";
1365 		PutString( version, stream );
1366 		(*stream) << "\" ";
1367 	}
1368 	if ( !encoding.empty() )
1369 	{
1370 		(*stream) << "encoding=\"";
1371 		PutString( encoding, stream );
1372 		(*stream ) << "\" ";
1373 	}
1374 	if ( !standalone.empty() )
1375 	{
1376 		(*stream) << "standalone=\"";
1377 		PutString( standalone, stream );
1378 		(*stream) << "\" ";
1379 	}
1380 	(*stream) << "?>";
1381 }
1382 
1383 
CopyTo(TiXmlDeclaration * target) const1384 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1385 {
1386 	TiXmlNode::CopyTo( target );
1387 
1388 	target->version = version;
1389 	target->encoding = encoding;
1390 	target->standalone = standalone;
1391 }
1392 
1393 
Clone() const1394 TiXmlNode* TiXmlDeclaration::Clone() const
1395 {
1396 	TiXmlDeclaration* clone = new TiXmlDeclaration();
1397 
1398 	if ( !clone )
1399 		return 0;
1400 
1401 	CopyTo( clone );
1402 	return clone;
1403 }
1404 
1405 
Print(TIXML_OSTREAM & cfile,int depth) const1406 void TiXmlUnknown::Print( TIXML_OSTREAM& cfile, int depth ) const
1407 {
1408 	for ( int i=0; i<depth; i++ )
1409 		cfile << "    ";
1410 	cfile << '<' << value << '>';
1411 }
1412 
1413 
StreamOut(TIXML_OSTREAM * stream) const1414 void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
1415 {
1416 	(*stream) << "<" << value << ">";		// Don't use entities here! It is unknown.
1417 }
1418 
1419 
CopyTo(TiXmlUnknown * target) const1420 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1421 {
1422 	TiXmlNode::CopyTo( target );
1423 }
1424 
1425 
Clone() const1426 TiXmlNode* TiXmlUnknown::Clone() const
1427 {
1428 	TiXmlUnknown* clone = new TiXmlUnknown();
1429 
1430 	if ( !clone )
1431 		return 0;
1432 
1433 	CopyTo( clone );
1434 	return clone;
1435 }
1436 
1437 
TiXmlAttributeSet()1438 TiXmlAttributeSet::TiXmlAttributeSet()
1439 {
1440 	sentinel.next = &sentinel;
1441 	sentinel.prev = &sentinel;
1442 }
1443 
1444 
~TiXmlAttributeSet()1445 TiXmlAttributeSet::~TiXmlAttributeSet()
1446 {
1447 	assert( sentinel.next == &sentinel );
1448 	assert( sentinel.prev == &sentinel );
1449 }
1450 
1451 
Add(TiXmlAttribute * addMe)1452 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1453 {
1454 	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
1455 
1456 	addMe->next = &sentinel;
1457 	addMe->prev = sentinel.prev;
1458 
1459 	sentinel.prev->next = addMe;
1460 	sentinel.prev      = addMe;
1461 }
1462 
Remove(TiXmlAttribute * removeMe)1463 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1464 {
1465 	TiXmlAttribute* node;
1466 
1467 	for( node = sentinel.next; node != &sentinel; node = node->next )
1468 	{
1469 		if ( node == removeMe )
1470 		{
1471 			node->prev->next = node->next;
1472 			node->next->prev = node->prev;
1473 			node->next = 0;
1474 			node->prev = 0;
1475 			return;
1476 		}
1477 	}
1478 	assert( 0 );		// we tried to remove a non-linked attribute.
1479 }
1480 
Find(const char * name) const1481 const TiXmlAttribute*	TiXmlAttributeSet::Find( const char * name ) const
1482 {
1483 	const TiXmlAttribute* node;
1484 
1485 	for( node = sentinel.next; node != &sentinel; node = node->next )
1486 	{
1487 		if ( node->name == name )
1488 			return node;
1489 	}
1490 	return 0;
1491 }
1492 
Find(const char * name)1493 TiXmlAttribute*	TiXmlAttributeSet::Find( const char * name )
1494 {
1495 	TiXmlAttribute* node;
1496 
1497 	for( node = sentinel.next; node != &sentinel; node = node->next )
1498 	{
1499 		if ( node->name == name )
1500 			return node;
1501 	}
1502 	return 0;
1503 }
1504 
1505 #ifdef TIXML_USE_STL
operator >>(TIXML_ISTREAM & in,TiXmlNode & base)1506 TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
1507 {
1508 	TIXML_STRING tag;
1509 	tag.reserve( 8 * 1000 );
1510 	base.StreamIn( &in, &tag );
1511 
1512 	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1513 	return in;
1514 }
1515 #endif
1516 
1517 
operator <<(TIXML_OSTREAM & out,const TiXmlNode & base)1518 TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
1519 {
1520 	base.StreamOut (& out);
1521 	return out;
1522 }
1523 
1524 
1525 #ifdef TIXML_USE_STL
operator <<(std::string & out,const TiXmlNode & base)1526 std::string & operator<< (std::string& out, const TiXmlNode& base )
1527 {
1528    std::ostringstream os_stream( std::ostringstream::out );
1529    base.StreamOut( &os_stream );
1530 
1531    out.append( os_stream.str() );
1532    return out;
1533 }
1534 #endif
1535 
1536 
FirstChild() const1537 TiXmlHandle TiXmlHandle::FirstChild() const
1538 {
1539 	if ( node )
1540 	{
1541 		TiXmlNode* child = node->FirstChild();
1542 		if ( child )
1543 			return TiXmlHandle( child );
1544 	}
1545 	return TiXmlHandle( 0 );
1546 }
1547 
1548 
FirstChild(const char * value) const1549 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1550 {
1551 	if ( node )
1552 	{
1553 		TiXmlNode* child = node->FirstChild( value );
1554 		if ( child )
1555 			return TiXmlHandle( child );
1556 	}
1557 	return TiXmlHandle( 0 );
1558 }
1559 
1560 
FirstChildElement() const1561 TiXmlHandle TiXmlHandle::FirstChildElement() const
1562 {
1563 	if ( node )
1564 	{
1565 		TiXmlElement* child = node->FirstChildElement();
1566 		if ( child )
1567 			return TiXmlHandle( child );
1568 	}
1569 	return TiXmlHandle( 0 );
1570 }
1571 
1572 
FirstChildElement(const char * value) const1573 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1574 {
1575 	if ( node )
1576 	{
1577 		TiXmlElement* child = node->FirstChildElement( value );
1578 		if ( child )
1579 			return TiXmlHandle( child );
1580 	}
1581 	return TiXmlHandle( 0 );
1582 }
1583 
1584 
Child(int count) const1585 TiXmlHandle TiXmlHandle::Child( int count ) const
1586 {
1587 	if ( node )
1588 	{
1589 		int i;
1590 		TiXmlNode* child = node->FirstChild();
1591 		for (	i=0;
1592 				child && i<count;
1593 				child = child->NextSibling(), ++i )
1594 		{
1595 			// nothing
1596 		}
1597 		if ( child )
1598 			return TiXmlHandle( child );
1599 	}
1600 	return TiXmlHandle( 0 );
1601 }
1602 
1603 
Child(const char * value,int count) const1604 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1605 {
1606 	if ( node )
1607 	{
1608 		int i;
1609 		TiXmlNode* child = node->FirstChild( value );
1610 		for (	i=0;
1611 				child && i<count;
1612 				child = child->NextSibling( value ), ++i )
1613 		{
1614 			// nothing
1615 		}
1616 		if ( child )
1617 			return TiXmlHandle( child );
1618 	}
1619 	return TiXmlHandle( 0 );
1620 }
1621 
1622 
ChildElement(int count) const1623 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1624 {
1625 	if ( node )
1626 	{
1627 		int i;
1628 		TiXmlElement* child = node->FirstChildElement();
1629 		for (	i=0;
1630 				child && i<count;
1631 				child = child->NextSiblingElement(), ++i )
1632 		{
1633 			// nothing
1634 		}
1635 		if ( child )
1636 			return TiXmlHandle( child );
1637 	}
1638 	return TiXmlHandle( 0 );
1639 }
1640 
1641 
ChildElement(const char * value,int count) const1642 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1643 {
1644 	if ( node )
1645 	{
1646 		int i;
1647 		TiXmlElement* child = node->FirstChildElement( value );
1648 		for (	i=0;
1649 				child && i<count;
1650 				child = child->NextSiblingElement( value ), ++i )
1651 		{
1652 			// nothing
1653 		}
1654 		if ( child )
1655 			return TiXmlHandle( child );
1656 	}
1657 	return TiXmlHandle( 0 );
1658 }
1659