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