PageRenderTime 142ms CodeModel.GetById 14ms app.highlight 118ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/tinyxml/tinyxml.cpp

http://crashrpt.googlecode.com/
C++ | 1839 lines | 1407 code | 320 blank | 112 comment | 251 complexity | 9f8429b8e9b6316a778ff49557e23f4b MD5 | raw file
   1/*
   2www.sourceforge.net/projects/tinyxml
   3Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
   4
   5This software is provided 'as-is', without any express or implied
   6warranty. In no event will the authors be held liable for any
   7damages arising from the use of this software.
   8
   9Permission is granted to anyone to use this software for any
  10purpose, including commercial applications, and to alter it and
  11redistribute it freely, subject to the following restrictions:
  12
  131. The origin of this software must not be misrepresented; you must
  14not claim that you wrote the original software. If you use this
  15software in a product, an acknowledgment in the product documentation
  16would be appreciated but is not required.
  17
  182. Altered source versions must be plainly marked as such, and
  19must not be misrepresented as being the original software.
  20
  213. This notice may not be removed or altered from any source
  22distribution.
  23*/
  24
  25#include <ctype.h>
  26
  27#ifdef TIXML_USE_STL
  28#include <sstream>
  29#include <iostream>
  30#endif
  31
  32#include "tinyxml.h"
  33
  34FILE* TiXmlFOpen( const char* filename, const char* mode );
  35
  36bool TiXmlBase::condenseWhiteSpace = true;
  37
  38// Microsoft compiler security
  39FILE* TiXmlFOpen( const char* filename, const char* mode )
  40{
  41	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
  42		FILE* fp = 0;
  43		errno_t err = fopen_s( &fp, filename, mode );
  44		if ( !err && fp )
  45			return fp;
  46		return 0;
  47	#else
  48		return fopen( filename, mode );
  49	#endif
  50}
  51
  52void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
  53{
  54	int i=0;
  55
  56	while( i<(int)str.length() )
  57	{
  58		unsigned char c = (unsigned char) str[i];
  59
  60		if (    c == '&' 
  61		     && i < ( (int)str.length() - 2 )
  62			 && str[i+1] == '#'
  63			 && str[i+2] == 'x' )
  64		{
  65			// Hexadecimal character reference.
  66			// Pass through unchanged.
  67			// &#xA9;	-- copyright symbol, for example.
  68			//
  69			// The -1 is a bug fix from Rob Laveaux. It keeps
  70			// an overflow from happening if there is no ';'.
  71			// There are actually 2 ways to exit this loop -
  72			// while fails (error case) and break (semicolon found).
  73			// However, there is no mechanism (currently) for
  74			// this function to return an error.
  75			while ( i<(int)str.length()-1 )
  76			{
  77				outString->append( str.c_str() + i, 1 );
  78				++i;
  79				if ( str[i] == ';' )
  80					break;
  81			}
  82		}
  83		else if ( c == '&' )
  84		{
  85			outString->append( entity[0].str, entity[0].strLength );
  86			++i;
  87		}
  88		else if ( c == '<' )
  89		{
  90			outString->append( entity[1].str, entity[1].strLength );
  91			++i;
  92		}
  93		else if ( c == '>' )
  94		{
  95			outString->append( entity[2].str, entity[2].strLength );
  96			++i;
  97		}
  98		else if ( c == '\"' )
  99		{
 100			outString->append( entity[3].str, entity[3].strLength );
 101			++i;
 102		}
 103		else if ( c == '\'' )
 104		{
 105			outString->append( entity[4].str, entity[4].strLength );
 106			++i;
 107		}
 108		else if ( c < 32 )
 109		{
 110			// Easy pass at non-alpha/numeric/symbol
 111			// Below 32 is symbolic.
 112			char buf[ 32 ];
 113			
 114			#if defined(TIXML_SNPRINTF)		
 115				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
 116			#else
 117				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
 118			#endif		
 119
 120			//*ME:	warning C4267: convert 'size_t' to 'int'
 121			//*ME:	Int-Cast to make compiler happy ...
 122			outString->append( buf, (int)strlen( buf ) );
 123			++i;
 124		}
 125		else
 126		{
 127			//char realc = (char) c;
 128			//outString->append( &realc, 1 );
 129			*outString += (char) c;	// somewhat more efficient function call.
 130			++i;
 131		}
 132	}
 133}
 134
 135
 136TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
 137{
 138	parent = 0;
 139	type = _type;
 140	firstChild = 0;
 141	lastChild = 0;
 142	prev = 0;
 143	next = 0;
 144}
 145
 146
 147TiXmlNode::~TiXmlNode()
 148{
 149	TiXmlNode* node = firstChild;
 150	TiXmlNode* temp = 0;
 151
 152	while ( node )
 153	{
 154		temp = node;
 155		node = node->next;
 156		delete temp;
 157	}	
 158}
 159
 160
 161void TiXmlNode::CopyTo( TiXmlNode* target ) const
 162{
 163	target->SetValue (value.c_str() );
 164	target->userData = userData; 
 165	target->location = location;
 166}
 167
 168
 169void 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
 186TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
 187{
 188	assert( node->parent == 0 || node->parent == this );
 189	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
 190
 191	if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
 192	{
 193		delete node;
 194		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 195		return 0;
 196	}
 197
 198	node->parent = this;
 199
 200	node->prev = lastChild;
 201	node->next = 0;
 202
 203	if ( lastChild )
 204		lastChild->next = node;
 205	else
 206		firstChild = node;			// it was an empty list.
 207
 208	lastChild = node;
 209	return node;
 210}
 211
 212
 213TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
 214{
 215	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
 216	{
 217		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 218		return 0;
 219	}
 220	TiXmlNode* node = addThis.Clone();
 221	if ( !node )
 222		return 0;
 223
 224	return LinkEndChild( node );
 225}
 226
 227
 228TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
 229{	
 230	if ( !beforeThis || beforeThis->parent != this ) {
 231		return 0;
 232	}
 233	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
 234	{
 235		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 236		return 0;
 237	}
 238
 239	TiXmlNode* node = addThis.Clone();
 240	if ( !node )
 241		return 0;
 242	node->parent = this;
 243
 244	node->next = beforeThis;
 245	node->prev = beforeThis->prev;
 246	if ( beforeThis->prev )
 247	{
 248		beforeThis->prev->next = node;
 249	}
 250	else
 251	{
 252		assert( firstChild == beforeThis );
 253		firstChild = node;
 254	}
 255	beforeThis->prev = node;
 256	return node;
 257}
 258
 259
 260TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
 261{
 262	if ( !afterThis || afterThis->parent != this ) {
 263		return 0;
 264	}
 265	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
 266	{
 267		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 268		return 0;
 269	}
 270
 271	TiXmlNode* node = addThis.Clone();
 272	if ( !node )
 273		return 0;
 274	node->parent = this;
 275
 276	node->prev = afterThis;
 277	node->next = afterThis->next;
 278	if ( afterThis->next )
 279	{
 280		afterThis->next->prev = node;
 281	}
 282	else
 283	{
 284		assert( lastChild == afterThis );
 285		lastChild = node;
 286	}
 287	afterThis->next = node;
 288	return node;
 289}
 290
 291
 292TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
 293{
 294	if ( !replaceThis )
 295		return 0;
 296
 297	if ( replaceThis->parent != this )
 298		return 0;
 299
 300	if ( withThis.ToDocument() ) {
 301		// A document can never be a child.	Thanks to Noam.
 302		TiXmlDocument* document = GetDocument();
 303		if ( document ) 
 304			document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 305		return 0;
 306	}
 307
 308	TiXmlNode* node = withThis.Clone();
 309	if ( !node )
 310		return 0;
 311
 312	node->next = replaceThis->next;
 313	node->prev = replaceThis->prev;
 314
 315	if ( replaceThis->next )
 316		replaceThis->next->prev = node;
 317	else
 318		lastChild = node;
 319
 320	if ( replaceThis->prev )
 321		replaceThis->prev->next = node;
 322	else
 323		firstChild = node;
 324
 325	delete replaceThis;
 326	node->parent = this;
 327	return node;
 328}
 329
 330
 331bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
 332{
 333	if ( !removeThis ) {
 334		return false;
 335	}
 336
 337	if ( removeThis->parent != this )
 338	{	
 339		assert( 0 );
 340		return false;
 341	}
 342
 343	if ( removeThis->next )
 344		removeThis->next->prev = removeThis->prev;
 345	else
 346		lastChild = removeThis->prev;
 347
 348	if ( removeThis->prev )
 349		removeThis->prev->next = removeThis->next;
 350	else
 351		firstChild = removeThis->next;
 352
 353	delete removeThis;
 354	return true;
 355}
 356
 357const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
 358{
 359	const TiXmlNode* node;
 360	for ( node = firstChild; node; node = node->next )
 361	{
 362		if ( strcmp( node->Value(), _value ) == 0 )
 363			return node;
 364	}
 365	return 0;
 366}
 367
 368
 369const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
 370{
 371	const TiXmlNode* node;
 372	for ( node = lastChild; node; node = node->prev )
 373	{
 374		if ( strcmp( node->Value(), _value ) == 0 )
 375			return node;
 376	}
 377	return 0;
 378}
 379
 380
 381const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
 382{
 383	if ( !previous )
 384	{
 385		return FirstChild();
 386	}
 387	else
 388	{
 389		assert( previous->parent == this );
 390		return previous->NextSibling();
 391	}
 392}
 393
 394
 395const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
 396{
 397	if ( !previous )
 398	{
 399		return FirstChild( val );
 400	}
 401	else
 402	{
 403		assert( previous->parent == this );
 404		return previous->NextSibling( val );
 405	}
 406}
 407
 408
 409const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 
 410{
 411	const TiXmlNode* node;
 412	for ( node = next; node; node = node->next )
 413	{
 414		if ( strcmp( node->Value(), _value ) == 0 )
 415			return node;
 416	}
 417	return 0;
 418}
 419
 420
 421const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
 422{
 423	const TiXmlNode* node;
 424	for ( node = prev; node; node = node->prev )
 425	{
 426		if ( strcmp( node->Value(), _value ) == 0 )
 427			return node;
 428	}
 429	return 0;
 430}
 431
 432
 433void TiXmlElement::RemoveAttribute( const char * name )
 434{
 435    #ifdef TIXML_USE_STL
 436	TIXML_STRING str( name );
 437	TiXmlAttribute* node = attributeSet.Find( str );
 438	#else
 439	TiXmlAttribute* node = attributeSet.Find( name );
 440	#endif
 441	if ( node )
 442	{
 443		attributeSet.Remove( node );
 444		delete node;
 445	}
 446}
 447
 448const TiXmlElement* TiXmlNode::FirstChildElement() const
 449{
 450	const TiXmlNode* node;
 451
 452	for (	node = FirstChild();
 453			node;
 454			node = node->NextSibling() )
 455	{
 456		if ( node->ToElement() )
 457			return node->ToElement();
 458	}
 459	return 0;
 460}
 461
 462
 463const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
 464{
 465	const TiXmlNode* node;
 466
 467	for (	node = FirstChild( _value );
 468			node;
 469			node = node->NextSibling( _value ) )
 470	{
 471		if ( node->ToElement() )
 472			return node->ToElement();
 473	}
 474	return 0;
 475}
 476
 477
 478const TiXmlElement* TiXmlNode::NextSiblingElement() const
 479{
 480	const TiXmlNode* node;
 481
 482	for (	node = NextSibling();
 483			node;
 484			node = node->NextSibling() )
 485	{
 486		if ( node->ToElement() )
 487			return node->ToElement();
 488	}
 489	return 0;
 490}
 491
 492
 493const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
 494{
 495	const TiXmlNode* node;
 496
 497	for (	node = NextSibling( _value );
 498			node;
 499			node = node->NextSibling( _value ) )
 500	{
 501		if ( node->ToElement() )
 502			return node->ToElement();
 503	}
 504	return 0;
 505}
 506
 507
 508const TiXmlDocument* TiXmlNode::GetDocument() const
 509{
 510	const TiXmlNode* node;
 511
 512	for( node = this; node; node = node->parent )
 513	{
 514		if ( node->ToDocument() )
 515			return node->ToDocument();
 516	}
 517	return 0;
 518}
 519
 520
 521TiXmlElement::TiXmlElement (const char * _value)
 522	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 523{
 524	firstChild = lastChild = 0;
 525	value = _value;
 526}
 527
 528
 529#ifdef TIXML_USE_STL
 530TiXmlElement::TiXmlElement( const std::string& _value ) 
 531	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 532{
 533	firstChild = lastChild = 0;
 534	value = _value;
 535}
 536#endif
 537
 538
 539TiXmlElement::TiXmlElement( const TiXmlElement& copy)
 540	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 541{
 542	firstChild = lastChild = 0;
 543	copy.CopyTo( this );	
 544}
 545
 546
 547void TiXmlElement::operator=( const TiXmlElement& base )
 548{
 549	ClearThis();
 550	base.CopyTo( this );
 551}
 552
 553
 554TiXmlElement::~TiXmlElement()
 555{
 556	ClearThis();
 557}
 558
 559
 560void TiXmlElement::ClearThis()
 561{
 562	Clear();
 563	while( attributeSet.First() )
 564	{
 565		TiXmlAttribute* node = attributeSet.First();
 566		attributeSet.Remove( node );
 567		delete node;
 568	}
 569}
 570
 571
 572const char* TiXmlElement::Attribute( const char* name ) const
 573{
 574	const TiXmlAttribute* node = attributeSet.Find( name );
 575	if ( node )
 576		return node->Value();
 577	return 0;
 578}
 579
 580
 581#ifdef TIXML_USE_STL
 582const std::string* TiXmlElement::Attribute( const std::string& name ) const
 583{
 584	const TiXmlAttribute* attrib = attributeSet.Find( name );
 585	if ( attrib )
 586		return &attrib->ValueStr();
 587	return 0;
 588}
 589#endif
 590
 591
 592const char* TiXmlElement::Attribute( const char* name, int* i ) const
 593{
 594	const TiXmlAttribute* attrib = attributeSet.Find( name );
 595	const char* result = 0;
 596
 597	if ( attrib ) {
 598		result = attrib->Value();
 599		if ( i ) {
 600			attrib->QueryIntValue( i );
 601		}
 602	}
 603	return result;
 604}
 605
 606
 607#ifdef TIXML_USE_STL
 608const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
 609{
 610	const TiXmlAttribute* attrib = attributeSet.Find( name );
 611	const std::string* result = 0;
 612
 613	if ( attrib ) {
 614		result = &attrib->ValueStr();
 615		if ( i ) {
 616			attrib->QueryIntValue( i );
 617		}
 618	}
 619	return result;
 620}
 621#endif
 622
 623
 624const char* TiXmlElement::Attribute( const char* name, double* d ) const
 625{
 626	const TiXmlAttribute* attrib = attributeSet.Find( name );
 627	const char* result = 0;
 628
 629	if ( attrib ) {
 630		result = attrib->Value();
 631		if ( d ) {
 632			attrib->QueryDoubleValue( d );
 633		}
 634	}
 635	return result;
 636}
 637
 638
 639#ifdef TIXML_USE_STL
 640const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
 641{
 642	const TiXmlAttribute* attrib = attributeSet.Find( name );
 643	const std::string* result = 0;
 644
 645	if ( attrib ) {
 646		result = &attrib->ValueStr();
 647		if ( d ) {
 648			attrib->QueryDoubleValue( d );
 649		}
 650	}
 651	return result;
 652}
 653#endif
 654
 655
 656int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
 657{
 658	const TiXmlAttribute* attrib = attributeSet.Find( name );
 659	if ( !attrib )
 660		return TIXML_NO_ATTRIBUTE;
 661	return attrib->QueryIntValue( ival );
 662}
 663
 664
 665#ifdef TIXML_USE_STL
 666int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
 667{
 668	const TiXmlAttribute* attrib = attributeSet.Find( name );
 669	if ( !attrib )
 670		return TIXML_NO_ATTRIBUTE;
 671	return attrib->QueryIntValue( ival );
 672}
 673#endif
 674
 675
 676int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
 677{
 678	const TiXmlAttribute* attrib = attributeSet.Find( name );
 679	if ( !attrib )
 680		return TIXML_NO_ATTRIBUTE;
 681	return attrib->QueryDoubleValue( dval );
 682}
 683
 684
 685#ifdef TIXML_USE_STL
 686int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
 687{
 688	const TiXmlAttribute* attrib = attributeSet.Find( name );
 689	if ( !attrib )
 690		return TIXML_NO_ATTRIBUTE;
 691	return attrib->QueryDoubleValue( dval );
 692}
 693#endif
 694
 695
 696void TiXmlElement::SetAttribute( const char * name, int val )
 697{	
 698	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
 699	if ( attrib ) {
 700		attrib->SetIntValue( val );
 701	}
 702}
 703
 704
 705#ifdef TIXML_USE_STL
 706void TiXmlElement::SetAttribute( const std::string& name, int val )
 707{	
 708	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
 709	if ( attrib ) {
 710		attrib->SetIntValue( val );
 711	}
 712}
 713#endif
 714
 715
 716void TiXmlElement::SetDoubleAttribute( const char * name, double val )
 717{	
 718	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
 719	if ( attrib ) {
 720		attrib->SetDoubleValue( val );
 721	}
 722}
 723
 724
 725#ifdef TIXML_USE_STL
 726void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
 727{	
 728	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
 729	if ( attrib ) {
 730		attrib->SetDoubleValue( val );
 731	}
 732}
 733#endif 
 734
 735
 736void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
 737{
 738	TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
 739	if ( attrib ) {
 740		attrib->SetValue( cvalue );
 741	}
 742}
 743
 744
 745#ifdef TIXML_USE_STL
 746void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
 747{
 748	TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
 749	if ( attrib ) {
 750		attrib->SetValue( _value );
 751	}
 752}
 753#endif
 754
 755
 756void TiXmlElement::Print( FILE* cfile, int depth ) const
 757{
 758	int i;
 759	assert( cfile );
 760	for ( i=0; i<depth; i++ ) {
 761		fprintf( cfile, "    " );
 762	}
 763
 764	fprintf( cfile, "<%s", value.c_str() );
 765
 766	const TiXmlAttribute* attrib;
 767	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
 768	{
 769		fprintf( cfile, " " );
 770		attrib->Print( cfile, depth );
 771	}
 772
 773	// There are 3 different formatting approaches:
 774	// 1) An element without children is printed as a <foo /> node
 775	// 2) An element with only a text child is printed as <foo> text </foo>
 776	// 3) An element with children is printed on multiple lines.
 777	TiXmlNode* node;
 778	if ( !firstChild )
 779	{
 780		fprintf( cfile, " />" );
 781	}
 782	else if ( firstChild == lastChild && firstChild->ToText() )
 783	{
 784		fprintf( cfile, ">" );
 785		firstChild->Print( cfile, depth + 1 );
 786		fprintf( cfile, "</%s>", value.c_str() );
 787	}
 788	else
 789	{
 790		fprintf( cfile, ">" );
 791
 792		for ( node = firstChild; node; node=node->NextSibling() )
 793		{
 794			if ( !node->ToText() )
 795			{
 796				fprintf( cfile, "\n" );
 797			}
 798			node->Print( cfile, depth+1 );
 799		}
 800		fprintf( cfile, "\n" );
 801		for( i=0; i<depth; ++i ) {
 802			fprintf( cfile, "    " );
 803		}
 804		fprintf( cfile, "</%s>", value.c_str() );
 805	}
 806}
 807
 808
 809void TiXmlElement::CopyTo( TiXmlElement* target ) const
 810{
 811	// superclass:
 812	TiXmlNode::CopyTo( target );
 813
 814	// Element class: 
 815	// Clone the attributes, then clone the children.
 816	const TiXmlAttribute* attribute = 0;
 817	for(	attribute = attributeSet.First();
 818	attribute;
 819	attribute = attribute->Next() )
 820	{
 821		target->SetAttribute( attribute->Name(), attribute->Value() );
 822	}
 823
 824	TiXmlNode* node = 0;
 825	for ( node = firstChild; node; node = node->NextSibling() )
 826	{
 827		target->LinkEndChild( node->Clone() );
 828	}
 829}
 830
 831bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
 832{
 833	if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 
 834	{
 835		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
 836		{
 837			if ( !node->Accept( visitor ) )
 838				break;
 839		}
 840	}
 841	return visitor->VisitExit( *this );
 842}
 843
 844
 845TiXmlNode* TiXmlElement::Clone() const
 846{
 847	TiXmlElement* clone = new TiXmlElement( Value() );
 848	if ( !clone )
 849		return 0;
 850
 851	CopyTo( clone );
 852	return clone;
 853}
 854
 855
 856const char* TiXmlElement::GetText() const
 857{
 858	const TiXmlNode* child = this->FirstChild();
 859	if ( child ) {
 860		const TiXmlText* childText = child->ToText();
 861		if ( childText ) {
 862			return childText->Value();
 863		}
 864	}
 865	return 0;
 866}
 867
 868
 869TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 870{
 871	tabsize = 4;
 872	useMicrosoftBOM = false;
 873	ClearError();
 874}
 875
 876TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 877{
 878	tabsize = 4;
 879	useMicrosoftBOM = false;
 880	value = documentName;
 881	ClearError();
 882}
 883
 884
 885#ifdef TIXML_USE_STL
 886TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 887{
 888	tabsize = 4;
 889	useMicrosoftBOM = false;
 890    value = documentName;
 891	ClearError();
 892}
 893#endif
 894
 895
 896TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 897{
 898	copy.CopyTo( this );
 899}
 900
 901
 902void TiXmlDocument::operator=( const TiXmlDocument& copy )
 903{
 904	Clear();
 905	copy.CopyTo( this );
 906}
 907
 908
 909bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
 910{
 911	return LoadFile( Value(), encoding );
 912}
 913
 914
 915bool TiXmlDocument::SaveFile() const
 916{
 917	return SaveFile( Value() );
 918}
 919
 920bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
 921{
 922	TIXML_STRING filename( _filename );
 923	value = filename;
 924
 925	// reading in binary mode so that tinyxml can normalize the EOL
 926	FILE* file = TiXmlFOpen( value.c_str (), "rb" );	
 927
 928	if ( file )
 929	{
 930		bool result = LoadFile( file, encoding );
 931		fclose( file );
 932		return result;
 933	}
 934	else
 935	{
 936		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
 937		return false;
 938	}
 939}
 940
 941bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
 942{
 943	if ( !file ) 
 944	{
 945		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
 946		return false;
 947	}
 948
 949	// Delete the existing data:
 950	Clear();
 951	location.Clear();
 952
 953	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
 954	long length = 0;
 955	fseek( file, 0, SEEK_END );
 956	length = ftell( file );
 957	fseek( file, 0, SEEK_SET );
 958
 959	// Strange case, but good to handle up front.
 960	if ( length <= 0 )
 961	{
 962		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
 963		return false;
 964	}
 965
 966	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
 967	// 2.11 End-of-Line Handling
 968	// <snip>
 969	// <quote>
 970	// ...the XML processor MUST behave as if it normalized all line breaks in external 
 971	// parsed entities (including the document entity) on input, before parsing, by translating 
 972	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 
 973	// a single #xA character.
 974	// </quote>
 975	//
 976	// It is not clear fgets does that, and certainly isn't clear it works cross platform. 
 977	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
 978	// convention, and not work generally.
 979
 980	/*
 981	while( fgets( buf, sizeof(buf), file ) )
 982	{
 983		data += buf;
 984	}
 985	*/
 986
 987	char* buf = new char[ length+1 ];
 988	buf[0] = 0;
 989
 990	if ( fread( buf, length, 1, file ) != 1 ) {
 991		delete [] buf;
 992		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
 993		return false;
 994	}
 995
 996	// Process the buffer in place to normalize new lines. (See comment above.)
 997	// Copies from the 'p' to 'q' pointer, where p can advance faster if
 998	// a newline-carriage return is hit.
 999	//
1000	// Wikipedia:
1001	// Systems based on ASCII or a compatible character set use either LF  (Line feed, '\n', 0x0A, 10 in decimal) or 
1002	// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
1003	//		* LF:    Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
1004    //		* 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
1005    //		* CR:    Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
1006
1007	const char* p = buf;	// the read head
1008	char* q = buf;			// the write head
1009	const char CR = 0x0d;
1010	const char LF = 0x0a;
1011
1012	buf[length] = 0;
1013	while( *p ) {
1014		assert( p < (buf+length) );
1015		assert( q <= (buf+length) );
1016		assert( q <= p );
1017
1018		if ( *p == CR ) {
1019			*q++ = LF;
1020			p++;
1021			if ( *p == LF ) {		// check for CR+LF (and skip LF)
1022				p++;
1023			}
1024		}
1025		else {
1026			*q++ = *p++;
1027		}
1028	}
1029	assert( q <= (buf+length) );
1030	*q = 0;
1031
1032	Parse( buf, 0, encoding );
1033
1034	delete [] buf;
1035	return !Error();
1036}
1037
1038
1039bool TiXmlDocument::SaveFile( const char * filename ) const
1040{
1041	// The old c stuff lives on...
1042	FILE* fp = TiXmlFOpen( filename, "w" );
1043	if ( fp )
1044	{
1045		bool result = SaveFile( fp );
1046		fclose( fp );
1047		return result;
1048	}
1049	return false;
1050}
1051
1052
1053bool TiXmlDocument::SaveFile( FILE* fp ) const
1054{
1055	if ( useMicrosoftBOM ) 
1056	{
1057		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1058		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1059		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1060
1061		fputc( TIXML_UTF_LEAD_0, fp );
1062		fputc( TIXML_UTF_LEAD_1, fp );
1063		fputc( TIXML_UTF_LEAD_2, fp );
1064	}
1065	Print( fp, 0 );
1066	return (ferror(fp) == 0);
1067}
1068
1069
1070void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1071{
1072	TiXmlNode::CopyTo( target );
1073
1074	target->error = error;
1075	target->errorId = errorId;
1076	target->errorDesc = errorDesc;
1077	target->tabsize = tabsize;
1078	target->errorLocation = errorLocation;
1079	target->useMicrosoftBOM = useMicrosoftBOM;
1080
1081	TiXmlNode* node = 0;
1082	for ( node = firstChild; node; node = node->NextSibling() )
1083	{
1084		target->LinkEndChild( node->Clone() );
1085	}	
1086}
1087
1088
1089TiXmlNode* TiXmlDocument::Clone() const
1090{
1091	TiXmlDocument* clone = new TiXmlDocument();
1092	if ( !clone )
1093		return 0;
1094
1095	CopyTo( clone );
1096	return clone;
1097}
1098
1099
1100void TiXmlDocument::Print( FILE* cfile, int depth ) const
1101{
1102	assert( cfile );
1103	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1104	{
1105		node->Print( cfile, depth );
1106		fprintf( cfile, "\n" );
1107	}
1108}
1109
1110
1111bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1112{
1113	if ( visitor->VisitEnter( *this ) )
1114	{
1115		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1116		{
1117			if ( !node->Accept( visitor ) )
1118				break;
1119		}
1120	}
1121	return visitor->VisitExit( *this );
1122}
1123
1124
1125const TiXmlAttribute* TiXmlAttribute::Next() const
1126{
1127	// We are using knowledge of the sentinel. The sentinel
1128	// have a value or name.
1129	if ( next->value.empty() && next->name.empty() )
1130		return 0;
1131	return next;
1132}
1133
1134/*
1135TiXmlAttribute* TiXmlAttribute::Next()
1136{
1137	// We are using knowledge of the sentinel. The sentinel
1138	// have a value or name.
1139	if ( next->value.empty() && next->name.empty() )
1140		return 0;
1141	return next;
1142}
1143*/
1144
1145const TiXmlAttribute* TiXmlAttribute::Previous() const
1146{
1147	// We are using knowledge of the sentinel. The sentinel
1148	// have a value or name.
1149	if ( prev->value.empty() && prev->name.empty() )
1150		return 0;
1151	return prev;
1152}
1153
1154/*
1155TiXmlAttribute* TiXmlAttribute::Previous()
1156{
1157	// We are using knowledge of the sentinel. The sentinel
1158	// have a value or name.
1159	if ( prev->value.empty() && prev->name.empty() )
1160		return 0;
1161	return prev;
1162}
1163*/
1164
1165void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1166{
1167	TIXML_STRING n, v;
1168
1169	EncodeString( name, &n );
1170	EncodeString( value, &v );
1171
1172	if (value.find ('\"') == TIXML_STRING::npos) {
1173		if ( cfile ) {
1174		fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1175		}
1176		if ( str ) {
1177			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1178		}
1179	}
1180	else {
1181		if ( cfile ) {
1182		fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1183		}
1184		if ( str ) {
1185			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1186		}
1187	}
1188}
1189
1190
1191int TiXmlAttribute::QueryIntValue( int* ival ) const
1192{
1193	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1194		return TIXML_SUCCESS;
1195	return TIXML_WRONG_TYPE;
1196}
1197
1198int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1199{
1200	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1201		return TIXML_SUCCESS;
1202	return TIXML_WRONG_TYPE;
1203}
1204
1205void TiXmlAttribute::SetIntValue( int _value )
1206{
1207	char buf [64];
1208	#if defined(TIXML_SNPRINTF)		
1209		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1210	#else
1211		sprintf (buf, "%d", _value);
1212	#endif
1213	SetValue (buf);
1214}
1215
1216void TiXmlAttribute::SetDoubleValue( double _value )
1217{
1218	char buf [256];
1219	#if defined(TIXML_SNPRINTF)		
1220		TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
1221	#else
1222		sprintf (buf, "%g", _value);
1223	#endif
1224	SetValue (buf);
1225}
1226
1227int TiXmlAttribute::IntValue() const
1228{
1229	return atoi (value.c_str ());
1230}
1231
1232double  TiXmlAttribute::DoubleValue() const
1233{
1234	return atof (value.c_str ());
1235}
1236
1237
1238TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
1239{
1240	copy.CopyTo( this );
1241}
1242
1243
1244void TiXmlComment::operator=( const TiXmlComment& base )
1245{
1246	Clear();
1247	base.CopyTo( this );
1248}
1249
1250
1251void TiXmlComment::Print( FILE* cfile, int depth ) const
1252{
1253	assert( cfile );
1254	for ( int i=0; i<depth; i++ )
1255	{
1256		fprintf( cfile,  "    " );
1257	}
1258	fprintf( cfile, "<!--%s-->", value.c_str() );
1259}
1260
1261
1262void TiXmlComment::CopyTo( TiXmlComment* target ) const
1263{
1264	TiXmlNode::CopyTo( target );
1265}
1266
1267
1268bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1269{
1270	return visitor->Visit( *this );
1271}
1272
1273
1274TiXmlNode* TiXmlComment::Clone() const
1275{
1276	TiXmlComment* clone = new TiXmlComment();
1277
1278	if ( !clone )
1279		return 0;
1280
1281	CopyTo( clone );
1282	return clone;
1283}
1284
1285
1286void TiXmlText::Print( FILE* cfile, int depth ) const
1287{
1288	assert( cfile );
1289	if ( cdata )
1290	{
1291		int i;
1292		fprintf( cfile, "\n" );
1293		for ( i=0; i<depth; i++ ) {
1294			fprintf( cfile, "    " );
1295		}
1296		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
1297	}
1298	else
1299	{
1300		TIXML_STRING buffer;
1301		EncodeString( value, &buffer );
1302		fprintf( cfile, "%s", buffer.c_str() );
1303	}
1304}
1305
1306
1307void TiXmlText::CopyTo( TiXmlText* target ) const
1308{
1309	TiXmlNode::CopyTo( target );
1310	target->cdata = cdata;
1311}
1312
1313
1314bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1315{
1316	return visitor->Visit( *this );
1317}
1318
1319
1320TiXmlNode* TiXmlText::Clone() const
1321{	
1322	TiXmlText* clone = 0;
1323	clone = new TiXmlText( "" );
1324
1325	if ( !clone )
1326		return 0;
1327
1328	CopyTo( clone );
1329	return clone;
1330}
1331
1332
1333TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1334									const char * _encoding,
1335									const char * _standalone )
1336	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1337{
1338	version = _version;
1339	encoding = _encoding;
1340	standalone = _standalone;
1341}
1342
1343
1344#ifdef TIXML_USE_STL
1345TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
1346									const std::string& _encoding,
1347									const std::string& _standalone )
1348	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1349{
1350	version = _version;
1351	encoding = _encoding;
1352	standalone = _standalone;
1353}
1354#endif
1355
1356
1357TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1358	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1359{
1360	copy.CopyTo( this );	
1361}
1362
1363
1364void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1365{
1366	Clear();
1367	copy.CopyTo( this );
1368}
1369
1370
1371void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1372{
1373	if ( cfile ) fprintf( cfile, "<?xml " );
1374	if ( str )	 (*str) += "<?xml ";
1375
1376	if ( !version.empty() ) {
1377		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1378		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1379	}
1380	if ( !encoding.empty() ) {
1381		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1382		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1383	}
1384	if ( !standalone.empty() ) {
1385		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1386		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1387	}
1388	if ( cfile ) fprintf( cfile, "?>" );
1389	if ( str )	 (*str) += "?>";
1390}
1391
1392
1393void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1394{
1395	TiXmlNode::CopyTo( target );
1396
1397	target->version = version;
1398	target->encoding = encoding;
1399	target->standalone = standalone;
1400}
1401
1402
1403bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1404{
1405	return visitor->Visit( *this );
1406}
1407
1408
1409TiXmlNode* TiXmlDeclaration::Clone() const
1410{	
1411	TiXmlDeclaration* clone = new TiXmlDeclaration();
1412
1413	if ( !clone )
1414		return 0;
1415
1416	CopyTo( clone );
1417	return clone;
1418}
1419
1420
1421void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1422{
1423	for ( int i=0; i<depth; i++ )
1424		fprintf( cfile, "    " );
1425	fprintf( cfile, "<%s>", value.c_str() );
1426}
1427
1428
1429void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1430{
1431	TiXmlNode::CopyTo( target );
1432}
1433
1434
1435bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1436{
1437	return visitor->Visit( *this );
1438}
1439
1440
1441TiXmlNode* TiXmlUnknown::Clone() const
1442{
1443	TiXmlUnknown* clone = new TiXmlUnknown();
1444
1445	if ( !clone )
1446		return 0;
1447
1448	CopyTo( clone );
1449	return clone;
1450}
1451
1452
1453TiXmlAttributeSet::TiXmlAttributeSet()
1454{
1455	sentinel.next = &sentinel;
1456	sentinel.prev = &sentinel;
1457}
1458
1459
1460TiXmlAttributeSet::~TiXmlAttributeSet()
1461{
1462	assert( sentinel.next == &sentinel );
1463	assert( sentinel.prev == &sentinel );
1464}
1465
1466
1467void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1468{
1469    #ifdef TIXML_USE_STL
1470	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
1471	#else
1472	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
1473	#endif
1474
1475	addMe->next = &sentinel;
1476	addMe->prev = sentinel.prev;
1477
1478	sentinel.prev->next = addMe;
1479	sentinel.prev      = addMe;
1480}
1481
1482void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1483{
1484	TiXmlAttribute* node;
1485
1486	for( node = sentinel.next; node != &sentinel; node = node->next )
1487	{
1488		if ( node == removeMe )
1489		{
1490			node->prev->next = node->next;
1491			node->next->prev = node->prev;
1492			node->next = 0;
1493			node->prev = 0;
1494			return;
1495		}
1496	}
1497	assert( 0 );		// we tried to remove a non-linked attribute.
1498}
1499
1500
1501#ifdef TIXML_USE_STL
1502TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1503{
1504	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1505	{
1506		if ( node->name == name )
1507			return node;
1508	}
1509	return 0;
1510}
1511
1512TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
1513{
1514	TiXmlAttribute* attrib = Find( _name );
1515	if ( !attrib ) {
1516		attrib = new TiXmlAttribute();
1517		Add( attrib );
1518		attrib->SetName( _name );
1519	}
1520	return attrib;
1521}
1522#endif
1523
1524
1525TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1526{
1527	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1528	{
1529		if ( strcmp( node->name.c_str(), name ) == 0 )
1530			return node;
1531	}
1532	return 0;
1533}
1534
1535
1536TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
1537{
1538	TiXmlAttribute* attrib = Find( _name );
1539	if ( !attrib ) {
1540		attrib = new TiXmlAttribute();
1541		Add( attrib );
1542		attrib->SetName( _name );
1543	}
1544	return attrib;
1545}
1546
1547
1548#ifdef TIXML_USE_STL	
1549std::istream& operator>> (std::istream & in, TiXmlNode & base)
1550{
1551	TIXML_STRING tag;
1552	tag.reserve( 8 * 1000 );
1553	base.StreamIn( &in, &tag );
1554
1555	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1556	return in;
1557}
1558#endif
1559
1560
1561#ifdef TIXML_USE_STL	
1562std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1563{
1564	TiXmlPrinter printer;
1565	printer.SetStreamPrinting();
1566	base.Accept( &printer );
1567	out << printer.Str();
1568
1569	return out;
1570}
1571
1572
1573std::string& operator<< (std::string& out, const TiXmlNode& base )
1574{
1575	TiXmlPrinter printer;
1576	printer.SetStreamPrinting();
1577	base.Accept( &printer );
1578	out.append( printer.Str() );
1579
1580	return out;
1581}
1582#endif
1583
1584
1585TiXmlHandle TiXmlHandle::FirstChild() const
1586{
1587	if ( node )
1588	{
1589		TiXmlNode* child = node->FirstChild();
1590		if ( child )
1591			return TiXmlHandle( child );
1592	}
1593	return TiXmlHandle( 0 );
1594}
1595
1596
1597TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1598{
1599	if ( node )
1600	{
1601		TiXmlNode* child = node->FirstChild( value );
1602		if ( child )
1603			return TiXmlHandle( child );
1604	}
1605	return TiXmlHandle( 0 );
1606}
1607
1608
1609TiXmlHandle TiXmlHandle::FirstChildElement() const
1610{
1611	if ( node )
1612	{
1613		TiXmlElement* child = node->FirstChildElement();
1614		if ( child )
1615			return TiXmlHandle( child );
1616	}
1617	return TiXmlHandle( 0 );
1618}
1619
1620
1621TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1622{
1623	if ( node )
1624	{
1625		TiXmlElement* child = node->FirstChildElement( value );
1626		if ( child )
1627			return TiXmlHandle( child );
1628	}
1629	return TiXmlHandle( 0 );
1630}
1631
1632
1633TiXmlHandle TiXmlHandle::Child( int count ) const
1634{
1635	if ( node )
1636	{
1637		int i;
1638		TiXmlNode* child = node->FirstChild();
1639		for (	i=0;
1640				child && i<count;
1641				child = child->NextSibling(), ++i )
1642		{
1643			// nothing
1644		}
1645		if ( child )
1646			return TiXmlHandle( child );
1647	}
1648	return TiXmlHandle( 0 );
1649}
1650
1651
1652TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1653{
1654	if ( node )
1655	{
1656		int i;
1657		TiXmlNode* child = node->FirstChild( value );
1658		for (	i=0;
1659				child && i<count;
1660				child = child->NextSibling( value ), ++i )
1661		{
1662			// nothing
1663		}
1664		if ( child )
1665			return TiXmlHandle( child );
1666	}
1667	return TiXmlHandle( 0 );
1668}
1669
1670
1671TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1672{
1673	if ( node )
1674	{
1675		int i;
1676		TiXmlElement* child = node->FirstChildElement();
1677		for (	i=0;
1678				child && i<count;
1679				child = child->NextSiblingElement(), ++i )
1680		{
1681			// nothing
1682		}
1683		if ( child )
1684			return TiXmlHandle( child );
1685	}
1686	return TiXmlHandle( 0 );
1687}
1688
1689
1690TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1691{
1692	if ( node )
1693	{
1694		int i;
1695		TiXmlElement* child = node->FirstChildElement( value );
1696		for (	i=0;
1697				child && i<count;
1698				child = child->NextSiblingElement( value ), ++i )
1699		{
1700			// nothing
1701		}
1702		if ( child )
1703			return TiXmlHandle( child );
1704	}
1705	return TiXmlHandle( 0 );
1706}
1707
1708
1709bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1710{
1711	return true;
1712}
1713
1714bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1715{
1716	return true;
1717}
1718
1719bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1720{
1721	DoIndent();
1722	buffer += "<";
1723	buffer += element.Value();
1724
1725	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1726	{
1727		buffer += " ";
1728		attrib->Print( 0, 0, &buffer );
1729	}
1730
1731	if ( !element.FirstChild() ) 
1732	{
1733		buffer += " />";
1734		DoLineBreak();
1735	}
1736	else 
1737	{
1738		buffer += ">";
1739		if (    element.FirstChild()->ToText()
1740			  && element.LastChild() == element.FirstChild()
1741			  && element.FirstChild()->ToText()->CDATA() == false )
1742		{
1743			simpleTextPrint = true;
1744			// no DoLineBreak()!
1745		}
1746		else
1747		{
1748			DoLineBreak();
1749		}
1750	}
1751	++depth;	
1752	return true;
1753}
1754
1755
1756bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1757{
1758	--depth;
1759	if ( !element.FirstChild() ) 
1760	{
1761		// nothing.
1762	}
1763	else 
1764	{
1765		if ( simpleTextPrint )
1766		{
1767			simpleTextPrint = false;
1768		}
1769		else
1770		{
1771			DoIndent();
1772		}
1773		buffer += "</";
1774		buffer += element.Value();
1775		buffer += ">";
1776		DoLineBreak();
1777	}
1778	return true;
1779}
1780
1781
1782bool TiXmlPrinter::Visit( const TiXmlText& text )
1783{
1784	if ( text.CDATA() )
1785	{
1786		DoIndent();
1787		buffer += "<![CDATA[";
1788		buffer += text.Value();
1789		buffer += "]]>";
1790		DoLineBreak();
1791	}
1792	else if ( simpleTextPrint )
1793	{
1794		TIXML_STRING str;
1795		TiXmlBase::EncodeString( text.ValueTStr(), &str );
1796		buffer += str;
1797	}
1798	else
1799	{
1800		DoIndent();
1801		TIXML_STRING str;
1802		TiXmlBase::EncodeString( text.ValueTStr(), &str );
1803		buffer += str;
1804		DoLineBreak();
1805	}
1806	return true;
1807}
1808
1809
1810bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1811{
1812	DoIndent();
1813	declaration.Print( 0, 0, &buffer );
1814	DoLineBreak();
1815	return true;
1816}
1817
1818
1819bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1820{
1821	DoIndent();
1822	buffer += "<!--";
1823	buffer += comment.Value();
1824	buffer += "-->";
1825	DoLineBreak();
1826	return true;
1827}
1828
1829
1830bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1831{
1832	DoIndent();
1833	buffer += "<";
1834	buffer += unknown.Value();
1835	buffer += ">";
1836	DoLineBreak();
1837	return true;
1838}
1839