Update to version 2.6.2.

Change-Id: Ia9255d7c343e0a5c9bd22b951b189e347a119e0e
diff --git a/tinyxml.cpp b/tinyxml.cpp
index 5f84dec..9c161df 100644
--- a/tinyxml.cpp
+++ b/tinyxml.cpp
@@ -1,6 +1,6 @@
 /*
 www.sourceforge.net/projects/tinyxml
-Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+Original code by Lee Thomason (www.grinninglizard.com)
 
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any
@@ -23,23 +23,33 @@
 */
 
 #include <ctype.h>
-#include "tinyxml.h"
 
 #ifdef TIXML_USE_STL
 #include <sstream>
+#include <iostream>
 #endif
 
+#include "tinyxml.h"
+
+FILE* TiXmlFOpen( const char* filename, const char* mode );
 
 bool TiXmlBase::condenseWhiteSpace = true;
 
-void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
 {
-	TIXML_STRING buffer;
-	PutString( str, &buffer );
-	(*stream) << buffer;
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		FILE* fp = 0;
+		errno_t err = fopen_s( &fp, filename, mode );
+		if ( !err && fp )
+			return fp;
+		return 0;
+	#else
+		return fopen( filename, mode );
+	#endif
 }
 
-void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
 {
 	int i=0;
 
@@ -123,24 +133,6 @@
 }
 
 
-// <-- Strange class for a bug fix. Search for STL_STRING_BUG
-TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
-{
-	buffer = new char[ str.length()+1 ];
-	if ( buffer )
-	{
-		strcpy( buffer, str.c_str() );
-	}
-}
-
-
-TiXmlBase::StringToBuffer::~StringToBuffer()
-{
-	delete [] buffer;
-}
-// End strange bug fix. -->
-
-
 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
 {
 	parent = 0;
@@ -170,6 +162,7 @@
 {
 	target->SetValue (value.c_str() );
 	target->userData = userData; 
+	target->location = location;
 }
 
 
@@ -192,6 +185,17 @@
 
 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
 {
+	assert( node->parent == 0 || node->parent == this );
+	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+	if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		delete node;
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
 	node->parent = this;
 
 	node->prev = lastChild;
@@ -209,6 +213,12 @@
 
 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
 {
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
 	TiXmlNode* node = addThis.Clone();
 	if ( !node )
 		return 0;
@@ -219,8 +229,15 @@
 
 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
 {	
-	if ( !beforeThis || beforeThis->parent != this )
+	if ( !beforeThis || beforeThis->parent != this ) {
 		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
 
 	TiXmlNode* node = addThis.Clone();
 	if ( !node )
@@ -245,8 +262,15 @@
 
 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
 {
-	if ( !afterThis || afterThis->parent != this )
+	if ( !afterThis || afterThis->parent != this ) {
 		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
 
 	TiXmlNode* node = addThis.Clone();
 	if ( !node )
@@ -271,9 +295,20 @@
 
 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
 {
+	if ( !replaceThis )
+		return 0;
+
 	if ( replaceThis->parent != this )
 		return 0;
 
+	if ( withThis.ToDocument() ) {
+		// A document can never be a child.	Thanks to Noam.
+		TiXmlDocument* document = GetDocument();
+		if ( document ) 
+			document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
 	TiXmlNode* node = withThis.Clone();
 	if ( !node )
 		return 0;
@@ -299,6 +334,10 @@
 
 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
 {
+	if ( !removeThis ) {
+		return false;
+	}
+
 	if ( removeThis->parent != this )
 	{	
 		assert( 0 );
@@ -331,18 +370,6 @@
 }
 
 
-TiXmlNode* TiXmlNode::FirstChild( const char * _value )
-{
-	TiXmlNode* node;
-	for ( node = firstChild; node; node = node->next )
-	{
-		if ( strcmp( node->Value(), _value ) == 0 )
-			return node;
-	}
-	return 0;
-}
-
-
 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
 {
 	const TiXmlNode* node;
@@ -354,16 +381,6 @@
 	return 0;
 }
 
-TiXmlNode* TiXmlNode::LastChild( const char * _value )
-{
-	TiXmlNode* node;
-	for ( node = lastChild; node; node = node->prev )
-	{
-		if ( strcmp( node->Value(), _value ) == 0 )
-			return node;
-	}
-	return 0;
-}
 
 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
 {
@@ -378,18 +395,6 @@
 	}
 }
 
-TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
-{
-	if ( !previous )
-	{
-		return FirstChild();
-	}
-	else
-	{
-		assert( previous->parent == this );
-		return previous->NextSibling();
-	}
-}
 
 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
 {
@@ -404,18 +409,6 @@
 	}
 }
 
-TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
-{
-	if ( !previous )
-	{
-		return FirstChild( val );
-	}
-	else
-	{
-		assert( previous->parent == this );
-		return previous->NextSibling( val );
-	}
-}
 
 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 
 {
@@ -428,16 +421,6 @@
 	return 0;
 }
 
-TiXmlNode* TiXmlNode::NextSibling( const char * _value )
-{
-	TiXmlNode* node;
-	for ( node = next; node; node = node->next )
-	{
-		if ( strcmp( node->Value(), _value ) == 0 )
-			return node;
-	}
-	return 0;
-}
 
 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
 {
@@ -450,20 +433,15 @@
 	return 0;
 }
 
-TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
-{
-	TiXmlNode* node;
-	for ( node = prev; node; node = node->prev )
-	{
-		if ( strcmp( node->Value(), _value ) == 0 )
-			return node;
-	}
-	return 0;
-}
 
 void TiXmlElement::RemoveAttribute( const char * name )
 {
+    #ifdef TIXML_USE_STL
+	TIXML_STRING str( name );
+	TiXmlAttribute* node = attributeSet.Find( str );
+	#else
 	TiXmlAttribute* node = attributeSet.Find( name );
+	#endif
 	if ( node )
 	{
 		attributeSet.Remove( node );
@@ -485,19 +463,6 @@
 	return 0;
 }
 
-TiXmlElement* TiXmlNode::FirstChildElement()
-{
-	TiXmlNode* node;
-
-	for (	node = FirstChild();
-			node;
-			node = node->NextSibling() )
-	{
-		if ( node->ToElement() )
-			return node->ToElement();
-	}
-	return 0;
-}
 
 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
 {
@@ -513,27 +478,14 @@
 	return 0;
 }
 
-TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
-{
-	TiXmlNode* node;
-
-	for (	node = FirstChild( _value );
-			node;
-			node = node->NextSibling( _value ) )
-	{
-		if ( node->ToElement() )
-			return node->ToElement();
-	}
-	return 0;
-}
 
 const TiXmlElement* TiXmlNode::NextSiblingElement() const
 {
 	const TiXmlNode* node;
 
 	for (	node = NextSibling();
-	node;
-	node = node->NextSibling() )
+			node;
+			node = node->NextSibling() )
 	{
 		if ( node->ToElement() )
 			return node->ToElement();
@@ -541,41 +493,14 @@
 	return 0;
 }
 
-TiXmlElement* TiXmlNode::NextSiblingElement()
-{
-	TiXmlNode* node;
-
-	for (	node = NextSibling();
-	node;
-	node = node->NextSibling() )
-	{
-		if ( node->ToElement() )
-			return node->ToElement();
-	}
-	return 0;
-}
 
 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
 {
 	const TiXmlNode* node;
 
 	for (	node = NextSibling( _value );
-	node;
-	node = node->NextSibling( _value ) )
-	{
-		if ( node->ToElement() )
-			return node->ToElement();
-	}
-	return 0;
-}
-
-TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
-{
-	TiXmlNode* node;
-
-	for (	node = NextSibling( _value );
-	node;
-	node = node->NextSibling( _value ) )
+			node;
+			node = node->NextSibling( _value ) )
 	{
 		if ( node->ToElement() )
 			return node->ToElement();
@@ -596,20 +521,9 @@
 	return 0;
 }
 
-TiXmlDocument* TiXmlNode::GetDocument()
-{
-	TiXmlNode* node;
-
-	for( node = this; node; node = node->parent )
-	{
-		if ( node->ToDocument() )
-			return node->ToDocument();
-	}
-	return 0;
-}
 
 TiXmlElement::TiXmlElement (const char * _value)
-	: TiXmlNode( TiXmlNode::ELEMENT )
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 {
 	firstChild = lastChild = 0;
 	value = _value;
@@ -618,7 +532,7 @@
 
 #ifdef TIXML_USE_STL
 TiXmlElement::TiXmlElement( const std::string& _value ) 
-	: TiXmlNode( TiXmlNode::ELEMENT )
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 {
 	firstChild = lastChild = 0;
 	value = _value;
@@ -627,17 +541,18 @@
 
 
 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
-	: TiXmlNode( TiXmlNode::ELEMENT )
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
 {
 	firstChild = lastChild = 0;
 	copy.CopyTo( this );	
 }
 
 
-void TiXmlElement::operator=( const TiXmlElement& base )
+TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
 {
 	ClearThis();
 	base.CopyTo( this );
+	return *this;
 }
 
 
@@ -659,115 +574,234 @@
 }
 
 
-const char * TiXmlElement::Attribute( const char * name ) const
+const char* TiXmlElement::Attribute( const char* name ) const
 {
 	const TiXmlAttribute* node = attributeSet.Find( name );
-
 	if ( node )
 		return node->Value();
-
 	return 0;
 }
 
 
-const char * TiXmlElement::Attribute( const char * name, int* i ) const
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name ) const
 {
-	const char * s = Attribute( name );
-	if ( i )
-	{
-		if ( s )
-			*i = atoi( s );
-		else
-			*i = 0;
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( attrib )
+		return &attrib->ValueStr();
+	return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const char* result = 0;
+
+	if ( attrib ) {
+		result = attrib->Value();
+		if ( i ) {
+			attrib->QueryIntValue( i );
+		}
 	}
-	return s;
+	return result;
 }
 
 
-const char * TiXmlElement::Attribute( const char * name, double* d ) const
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
 {
-	const char * s = Attribute( name );
-	if ( d )
-	{
-		if ( s )
-			*d = atof( s );
-		else
-			*d = 0;
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const std::string* result = 0;
+
+	if ( attrib ) {
+		result = &attrib->ValueStr();
+		if ( i ) {
+			attrib->QueryIntValue( i );
+		}
 	}
-	return s;
+	return result;
 }
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const char* result = 0;
+
+	if ( attrib ) {
+		result = attrib->Value();
+		if ( d ) {
+			attrib->QueryDoubleValue( d );
+		}
+	}
+	return result;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const std::string* result = 0;
+
+	if ( attrib ) {
+		result = &attrib->ValueStr();
+		if ( d ) {
+			attrib->QueryDoubleValue( d );
+		}
+	}
+	return result;
+}
+#endif
 
 
 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
 {
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryIntValue( ival );
+}
+
+
+int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const
+{
 	const TiXmlAttribute* node = attributeSet.Find( name );
 	if ( !node )
 		return TIXML_NO_ATTRIBUTE;
 
-	return node->QueryIntValue( ival );
+	int ival = 0;
+	int result = node->QueryIntValue( &ival );
+	*value = (unsigned)ival;
+	return result;
 }
 
 
+int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	
+	int result = TIXML_WRONG_TYPE;
+	if (    StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) 
+		 || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) 
+		 || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) 
+	{
+		*bval = true;
+		result = TIXML_SUCCESS;
+	}
+	else if (    StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) 
+			  || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) 
+			  || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) 
+	{
+		*bval = false;
+		result = TIXML_SUCCESS;
+	}
+	return result;
+}
+
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryIntValue( ival );
+}
+#endif
+
+
 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
 {
-	const TiXmlAttribute* node = attributeSet.Find( name );
-	if ( !node )
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
 		return TIXML_NO_ATTRIBUTE;
-
-	return node->QueryDoubleValue( dval );
+	return attrib->QueryDoubleValue( dval );
 }
 
 
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryDoubleValue( dval );
+}
+#endif
+
+
 void TiXmlElement::SetAttribute( const char * name, int val )
 {	
-	char buf[64];
-	#if defined(TIXML_SNPRINTF)		
-		TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
-	#else
-		sprintf( buf, "%d", val );
-	#endif
-	SetAttribute( name, buf );
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetIntValue( val );
+	}
 }
 
 
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetIntValue( val );
+	}
+}
+#endif
+
+
 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
 {	
-	char buf[256];
-	#if defined(TIXML_SNPRINTF)		
-		TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
-	#else
-		sprintf( buf, "%f", val );
-	#endif
-	SetAttribute( name, buf );
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetDoubleValue( val );
+	}
 }
 
 
-void TiXmlElement::SetAttribute( const char * name, const char * _value )
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetDoubleValue( val );
+	}
+}
+#endif 
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
 {
-	TiXmlAttribute* node = attributeSet.Find( name );
-	if ( node )
-	{
-		node->SetValue( _value );
-		return;
-	}
-
-	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
-	if ( attrib )
-	{
-		attributeSet.Add( attrib );
-	}
-	else
-	{
-		TiXmlDocument* document = GetDocument();
-		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
+	if ( attrib ) {
+		attrib->SetValue( cvalue );
 	}
 }
 
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
+{
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
+	if ( attrib ) {
+		attrib->SetValue( _value );
+	}
+}
+#endif
+
+
 void TiXmlElement::Print( FILE* cfile, int depth ) const
 {
 	int i;
-	for ( i=0; i<depth; i++ )
-	{
+	assert( cfile );
+	for ( i=0; i<depth; i++ ) {
 		fprintf( cfile, "    " );
 	}
 
@@ -808,39 +842,10 @@
 			node->Print( cfile, depth+1 );
 		}
 		fprintf( cfile, "\n" );
-		for( i=0; i<depth; ++i )
-		fprintf( cfile, "    " );
-		fprintf( cfile, "</%s>", value.c_str() );
-	}
-}
-
-void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	(*stream) << "<" << value;
-
-	const TiXmlAttribute* attrib;
-	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
-	{	
-		(*stream) << " ";
-		attrib->StreamOut( stream );
-	}
-
-	// If this node has children, give it a closing tag. Else
-	// make it an empty tag.
-	TiXmlNode* node;
-	if ( firstChild )
-	{ 		
-		(*stream) << ">";
-
-		for ( node = firstChild; node; node=node->NextSibling() )
-		{
-			node->StreamOut( stream );
+		for( i=0; i<depth; ++i ) {
+			fprintf( cfile, "    " );
 		}
-		(*stream) << "</" << value << ">";
-	}
-	else
-	{
-		(*stream) << " />";
+		fprintf( cfile, "</%s>", value.c_str() );
 	}
 }
 
@@ -867,6 +872,19 @@
 	}
 }
 
+bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
+	}
+	return visitor->VisitExit( *this );
+}
+
 
 TiXmlNode* TiXmlElement::Clone() const
 {
@@ -892,14 +910,14 @@
 }
 
 
-TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 {
 	tabsize = 4;
 	useMicrosoftBOM = false;
 	ClearError();
 }
 
-TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 {
 	tabsize = 4;
 	useMicrosoftBOM = false;
@@ -909,7 +927,7 @@
 
 
 #ifdef TIXML_USE_STL
-TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 {
 	tabsize = 4;
 	useMicrosoftBOM = false;
@@ -919,200 +937,191 @@
 #endif
 
 
-TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
 {
 	copy.CopyTo( this );
 }
 
 
-void TiXmlDocument::operator=( const TiXmlDocument& copy )
+TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
 {
 	Clear();
 	copy.CopyTo( this );
+	return *this;
 }
 
 
 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
 {
-	// See STL_STRING_BUG below.
-	StringToBuffer buf( value );
-
-	if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
-		return true;
-
-	return false;
+	return LoadFile( Value(), encoding );
 }
 
 
 bool TiXmlDocument::SaveFile() const
 {
-	// See STL_STRING_BUG below.
-	StringToBuffer buf( value );
-
-	if ( buf.buffer && SaveFile( buf.buffer ) )
-		return true;
-
-	return false;
+	return SaveFile( Value() );
 }
 
-bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
 {
+	TIXML_STRING filename( _filename );
+	value = filename;
+
+	// reading in binary mode so that tinyxml can normalize the EOL
+	FILE* file = TiXmlFOpen( value.c_str (), "rb" );	
+
+	if ( file )
+	{
+		bool result = LoadFile( file, encoding );
+		fclose( file );
+		return result;
+	}
+	else
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+	if ( !file ) 
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
 	// Delete the existing data:
 	Clear();
 	location.Clear();
 
-	// There was a really terrifying little bug here. The code:
-	//		value = filename
-	// in the STL case, cause the assignment method of the std::string to
-	// be called. What is strange, is that the std::string had the same
-	// address as it's c_str() method, and so bad things happen. Looks
-	// like a bug in the Microsoft STL implementation.
-	// See STL_STRING_BUG above.
-	// Fixed with the StringToBuffer class.
-	value = filename;
+	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
+	long length = 0;
+	fseek( file, 0, SEEK_END );
+	length = ftell( file );
+	fseek( file, 0, SEEK_SET );
 
-	// reading in binary mode so that tinyxml can normalize the EOL
-	FILE* file = fopen( value.c_str (), "rb" );	
-
-	if ( file )
+	// Strange case, but good to handle up front.
+	if ( length <= 0 )
 	{
-		// Get the file size, so we can pre-allocate the string. HUGE speed impact.
-		long length = 0;
-		fseek( file, 0, SEEK_END );
-		length = ftell( file );
-		fseek( file, 0, SEEK_SET );
-
-		// Strange case, but good to handle up front.
-		if ( length == 0 )
-		{
-			fclose( file );
-			return false;
-		}
-
-		// If we have a file, assume it is all one big XML file, and read it in.
-		// The document parser may decide the document ends sooner than the entire file, however.
-		TIXML_STRING data;
-		data.reserve( length );
-
-		// Subtle bug here. TinyXml did use fgets. But from the XML spec:
-		// 2.11 End-of-Line Handling
-		// <snip>
-		// <quote>
-		// ...the XML processor MUST behave as if it normalized all line breaks in external 
-		// parsed entities (including the document entity) on input, before parsing, by translating 
-		// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 
-		// a single #xA character.
-		// </quote>
-		//
-		// It is not clear fgets does that, and certainly isn't clear it works cross platform. 
-		// Generally, you expect fgets to translate from the convention of the OS to the c/unix
-		// convention, and not work generally.
-
-		/*
-		while( fgets( buf, sizeof(buf), file ) )
-		{
-			data += buf;
-		}
-		*/
-
-		char* buf = new char[ length+1 ];
-		buf[0] = 0;
-
-		if ( fread( buf, length, 1, file ) != 1 ) {
-		//if ( fread( buf, 1, length, file ) != (size_t)length ) {
-			SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
-			fclose( file );
-			return false;
-		}
-		fclose( file );
-
-		const char* lastPos = buf;
-		const char* p = buf;
-
-		buf[length] = 0;
-		while( *p ) {
-			assert( p < (buf+length) );
-			if ( *p == 0xa ) {
-				// Newline character. No special rules for this. Append all the characters
-				// since the last string, and include the newline.
-				data.append( lastPos, p-lastPos+1 );	// append, include the newline
-				++p;									// move past the newline
-				lastPos = p;							// and point to the new buffer (may be 0)
-				assert( p <= (buf+length) );
-			}
-			else if ( *p == 0xd ) {
-				// Carriage return. Append what we have so far, then
-				// handle moving forward in the buffer.
-				if ( (p-lastPos) > 0 ) {
-					data.append( lastPos, p-lastPos );	// do not add the CR
-				}
-				data += (char)0xa;						// a proper newline
-
-				if ( *(p+1) == 0xa ) {
-					// Carriage return - new line sequence
-					p += 2;
-					lastPos = p;
-					assert( p <= (buf+length) );
-				}
-				else {
-					// it was followed by something else...that is presumably characters again.
-					++p;
-					lastPos = p;
-					assert( p <= (buf+length) );
-				}
-			}
-			else {
-				++p;
-			}
-		}
-		// Handle any left over characters.
-		if ( p-lastPos ) {
-			data.append( lastPos, p-lastPos );
-		}		
-		delete [] buf;
-		buf = 0;
-
-		Parse( data.c_str(), 0, encoding );
-
-		if (  Error() )
-            return false;
-        else
-			return true;
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
 	}
-	SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
-	return false;
+
+	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
+	// 2.11 End-of-Line Handling
+	// <snip>
+	// <quote>
+	// ...the XML processor MUST behave as if it normalized all line breaks in external 
+	// parsed entities (including the document entity) on input, before parsing, by translating 
+	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 
+	// a single #xA character.
+	// </quote>
+	//
+	// It is not clear fgets does that, and certainly isn't clear it works cross platform. 
+	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
+	// convention, and not work generally.
+
+	/*
+	while( fgets( buf, sizeof(buf), file ) )
+	{
+		data += buf;
+	}
+	*/
+
+	char* buf = new char[ length+1 ];
+	buf[0] = 0;
+
+	if ( fread( buf, length, 1, file ) != 1 ) {
+		delete [] buf;
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// Process the buffer in place to normalize new lines. (See comment above.)
+	// Copies from the 'p' to 'q' pointer, where p can advance faster if
+	// a newline-carriage return is hit.
+	//
+	// Wikipedia:
+	// Systems based on ASCII or a compatible character set use either LF  (Line feed, '\n', 0x0A, 10 in decimal) or 
+	// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
+	//		* LF:    Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
+    //		* 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
+    //		* CR:    Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
+
+	const char* p = buf;	// the read head
+	char* q = buf;			// the write head
+	const char CR = 0x0d;
+	const char LF = 0x0a;
+
+	buf[length] = 0;
+	while( *p ) {
+		assert( p < (buf+length) );
+		assert( q <= (buf+length) );
+		assert( q <= p );
+
+		if ( *p == CR ) {
+			*q++ = LF;
+			p++;
+			if ( *p == LF ) {		// check for CR+LF (and skip LF)
+				p++;
+			}
+		}
+		else {
+			*q++ = *p++;
+		}
+	}
+	assert( q <= (buf+length) );
+	*q = 0;
+
+	Parse( buf, 0, encoding );
+
+	delete [] buf;
+	return !Error();
 }
 
+
 bool TiXmlDocument::SaveFile( const char * filename ) const
 {
 	// The old c stuff lives on...
-	FILE* fp = fopen( filename, "w" );
+	FILE* fp = TiXmlFOpen( filename, "w" );
 	if ( fp )
 	{
-		if ( useMicrosoftBOM ) 
-		{
-			const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
-			const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
-			const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
-
-			fputc( TIXML_UTF_LEAD_0, fp );
-			fputc( TIXML_UTF_LEAD_1, fp );
-			fputc( TIXML_UTF_LEAD_2, fp );
-		}
-		Print( fp, 0 );
+		bool result = SaveFile( fp );
 		fclose( fp );
-		return true;
+		return result;
 	}
 	return false;
 }
 
 
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+	if ( useMicrosoftBOM ) 
+	{
+		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+		fputc( TIXML_UTF_LEAD_0, fp );
+		fputc( TIXML_UTF_LEAD_1, fp );
+		fputc( TIXML_UTF_LEAD_2, fp );
+	}
+	Print( fp, 0 );
+	return (ferror(fp) == 0);
+}
+
+
 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
 {
 	TiXmlNode::CopyTo( target );
 
 	target->error = error;
-	target->errorDesc = errorDesc.c_str ();
+	target->errorId = errorId;
+	target->errorDesc = errorDesc;
+	target->tabsize = tabsize;
+	target->errorLocation = errorLocation;
+	target->useMicrosoftBOM = useMicrosoftBOM;
 
 	TiXmlNode* node = 0;
 	for ( node = firstChild; node; node = node->NextSibling() )
@@ -1135,27 +1144,26 @@
 
 void TiXmlDocument::Print( FILE* cfile, int depth ) const
 {
-	const TiXmlNode* node;
-	for ( node=FirstChild(); node; node=node->NextSibling() )
+	assert( cfile );
+	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
 	{
 		node->Print( cfile, depth );
 		fprintf( cfile, "\n" );
 	}
 }
 
-void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
-{
-	const TiXmlNode* node;
-	for ( node=FirstChild(); node; node=node->NextSibling() )
-	{
-		node->StreamOut( out );
 
-		// Special rule for streams: stop after the root element.
-		// The stream in code will only read one element, so don't
-		// write more than one.
-		if ( node->ToElement() )
-			break;
+bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this ) )
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
 	}
+	return visitor->VisitExit( *this );
 }
 
 
@@ -1168,6 +1176,7 @@
 	return next;
 }
 
+/*
 TiXmlAttribute* TiXmlAttribute::Next()
 {
 	// We are using knowledge of the sentinel. The sentinel
@@ -1176,6 +1185,7 @@
 		return 0;
 	return next;
 }
+*/
 
 const TiXmlAttribute* TiXmlAttribute::Previous() const
 {
@@ -1186,6 +1196,7 @@
 	return prev;
 }
 
+/*
 TiXmlAttribute* TiXmlAttribute::Previous()
 {
 	// We are using knowledge of the sentinel. The sentinel
@@ -1194,49 +1205,44 @@
 		return 0;
 	return prev;
 }
+*/
 
-void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
 {
 	TIXML_STRING n, v;
 
-	PutString( name, &n );
-	PutString( value, &v );
+	EncodeString( name, &n );
+	EncodeString( value, &v );
 
-	if (value.find ('\"') == TIXML_STRING::npos)
-		fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
-	else
-		fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
-}
-
-
-void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	if (value.find( '\"' ) != TIXML_STRING::npos)
-	{
-		PutString( name, stream );
-		(*stream) << "=" << "'";
-		PutString( value, stream );
-		(*stream) << "'";
+	if (value.find ('\"') == TIXML_STRING::npos) {
+		if ( cfile ) {
+			fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
+		}
 	}
-	else
-	{
-		PutString( name, stream );
-		(*stream) << "=" << "\"";
-		PutString( value, stream );
-		(*stream) << "\"";
+	else {
+		if ( cfile ) {
+			fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
+		}
 	}
 }
 
+
 int TiXmlAttribute::QueryIntValue( int* ival ) const
 {
-	if ( sscanf( value.c_str(), "%d", ival ) == 1 )
+	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
 		return TIXML_SUCCESS;
 	return TIXML_WRONG_TYPE;
 }
 
 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
 {
-	if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
+	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
 		return TIXML_SUCCESS;
 	return TIXML_WRONG_TYPE;
 }
@@ -1256,9 +1262,9 @@
 {
 	char buf [256];
 	#if defined(TIXML_SNPRINTF)		
-		TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
+		TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
 	#else
-		sprintf (buf, "%lf", _value);
+		sprintf (buf, "%g", _value);
 	#endif
 	SetValue (buf);
 }
@@ -1274,36 +1280,30 @@
 }
 
 
-TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
 {
 	copy.CopyTo( this );
 }
 
 
-void TiXmlComment::operator=( const TiXmlComment& base )
+TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
 {
 	Clear();
 	base.CopyTo( this );
+	return *this;
 }
 
 
 void TiXmlComment::Print( FILE* cfile, int depth ) const
 {
+	assert( cfile );
 	for ( int i=0; i<depth; i++ )
 	{
-		fputs( "    ", cfile );
+		fprintf( cfile,  "    " );
 	}
 	fprintf( cfile, "<!--%s-->", value.c_str() );
 }
 
-void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	(*stream) << "<!--";
-	//PutString( value, stream );
-	(*stream) << value;
-	(*stream) << "-->";
-}
-
 
 void TiXmlComment::CopyTo( TiXmlComment* target ) const
 {
@@ -1311,6 +1311,12 @@
 }
 
 
+bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
 TiXmlNode* TiXmlComment::Clone() const
 {
 	TiXmlComment* clone = new TiXmlComment();
@@ -1325,6 +1331,7 @@
 
 void TiXmlText::Print( FILE* cfile, int depth ) const
 {
+	assert( cfile );
 	if ( cdata )
 	{
 		int i;
@@ -1332,38 +1339,17 @@
 		for ( i=0; i<depth; i++ ) {
 			fprintf( cfile, "    " );
 		}
-		fprintf( cfile, "<![CDATA[\n" );
-
-		fprintf( cfile, "%s", value.c_str() );	// unformatted output
-
-		fprintf( cfile, "\n" );
-		for ( i=0; i<depth; i++ ) {
-			fprintf( cfile, "    " );
-		}
-		fprintf( cfile, "]]>\n" );
+		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
 	}
 	else
 	{
 		TIXML_STRING buffer;
-		PutString( value, &buffer );
+		EncodeString( value, &buffer );
 		fprintf( cfile, "%s", buffer.c_str() );
 	}
 }
 
 
-void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	if ( cdata )
-	{
-		(*stream) << "<![CDATA[" << value << "]]>";
-	}
-	else
-	{
-		PutString( value, stream );
-	}
-}
-
-
 void TiXmlText::CopyTo( TiXmlText* target ) const
 {
 	TiXmlNode::CopyTo( target );
@@ -1371,6 +1357,12 @@
 }
 
 
+bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
 TiXmlNode* TiXmlText::Clone() const
 {	
 	TiXmlText* clone = 0;
@@ -1387,7 +1379,7 @@
 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
 									const char * _encoding,
 									const char * _standalone )
-	: TiXmlNode( TiXmlNode::DECLARATION )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
 {
 	version = _version;
 	encoding = _encoding;
@@ -1399,7 +1391,7 @@
 TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
 									const std::string& _encoding,
 									const std::string& _standalone )
-	: TiXmlNode( TiXmlNode::DECLARATION )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
 {
 	version = _version;
 	encoding = _encoding;
@@ -1409,55 +1401,39 @@
 
 
 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
-	: TiXmlNode( TiXmlNode::DECLARATION )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
 {
 	copy.CopyTo( this );	
 }
 
 
-void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
 {
 	Clear();
 	copy.CopyTo( this );
+	return *this;
 }
 
 
-void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
 {
-	fprintf (cfile, "<?xml ");
+	if ( cfile ) fprintf( cfile, "<?xml " );
+	if ( str )	 (*str) += "<?xml ";
 
-	if ( !version.empty() )
-		fprintf (cfile, "version=\"%s\" ", version.c_str ());
-	if ( !encoding.empty() )
-		fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
-	if ( !standalone.empty() )
-		fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
-	fprintf (cfile, "?>");
-}
-
-void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	(*stream) << "<?xml ";
-
-	if ( !version.empty() )
-	{
-		(*stream) << "version=\"";
-		PutString( version, stream );
-		(*stream) << "\" ";
+	if ( !version.empty() ) {
+		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
+		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
 	}
-	if ( !encoding.empty() )
-	{
-		(*stream) << "encoding=\"";
-		PutString( encoding, stream );
-		(*stream ) << "\" ";
+	if ( !encoding.empty() ) {
+		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
 	}
-	if ( !standalone.empty() )
-	{
-		(*stream) << "standalone=\"";
-		PutString( standalone, stream );
-		(*stream) << "\" ";
+	if ( !standalone.empty() ) {
+		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
 	}
-	(*stream) << "?>";
+	if ( cfile ) fprintf( cfile, "?>" );
+	if ( str )	 (*str) += "?>";
 }
 
 
@@ -1471,6 +1447,12 @@
 }
 
 
+bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
 TiXmlNode* TiXmlDeclaration::Clone() const
 {	
 	TiXmlDeclaration* clone = new TiXmlDeclaration();
@@ -1491,18 +1473,18 @@
 }
 
 
-void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
-{
-	(*stream) << "<" << value << ">";		// Don't use entities here! It is unknown.
-}
-
-
 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
 {
 	TiXmlNode::CopyTo( target );
 }
 
 
+bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
 TiXmlNode* TiXmlUnknown::Clone() const
 {
 	TiXmlUnknown* clone = new TiXmlUnknown();
@@ -1531,7 +1513,11 @@
 
 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
 {
+    #ifdef TIXML_USE_STL
+	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
+	#else
 	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
+	#endif
 
 	addMe->next = &sentinel;
 	addMe->prev = sentinel.prev;
@@ -1558,11 +1544,11 @@
 	assert( 0 );		// we tried to remove a non-linked attribute.
 }
 
-const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
-{
-	const TiXmlAttribute* node;
 
-	for( node = sentinel.next; node != &sentinel; node = node->next )
+#ifdef TIXML_USE_STL
+TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
 	{
 		if ( node->name == name )
 			return node;
@@ -1570,20 +1556,44 @@
 	return 0;
 }
 
-TiXmlAttribute*	TiXmlAttributeSet::Find( const char * name )
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
 {
-	TiXmlAttribute* node;
+	TiXmlAttribute* attrib = Find( _name );
+	if ( !attrib ) {
+		attrib = new TiXmlAttribute();
+		Add( attrib );
+		attrib->SetName( _name );
+	}
+	return attrib;
+}
+#endif
 
-	for( node = sentinel.next; node != &sentinel; node = node->next )
+
+TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
 	{
-		if ( node->name == name )
+		if ( strcmp( node->name.c_str(), name ) == 0 )
 			return node;
 	}
 	return 0;
 }
 
+
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
+{
+	TiXmlAttribute* attrib = Find( _name );
+	if ( !attrib ) {
+		attrib = new TiXmlAttribute();
+		Add( attrib );
+		attrib->SetName( _name );
+	}
+	return attrib;
+}
+
+
 #ifdef TIXML_USE_STL	
-TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
+std::istream& operator>> (std::istream & in, TiXmlNode & base)
 {
 	TIXML_STRING tag;
 	tag.reserve( 8 * 1000 );
@@ -1595,21 +1605,26 @@
 #endif
 
 
-TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
+#ifdef TIXML_USE_STL	
+std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
 {
-	base.StreamOut (& out);
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out << printer.Str();
+
 	return out;
 }
 
 
-#ifdef TIXML_USE_STL	
-std::string & operator<< (std::string& out, const TiXmlNode& base )
+std::string& operator<< (std::string& out, const TiXmlNode& base )
 {
-   std::ostringstream os_stream( std::ostringstream::out );
-   base.StreamOut( &os_stream );
-   
-   out.append( os_stream.str() );
-   return out;
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out.append( printer.Str() );
+
+	return out;
 }
 #endif
 
@@ -1736,3 +1751,136 @@
 	}
 	return TiXmlHandle( 0 );
 }
+
+
+bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += element.Value();
+
+	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
+	{
+		buffer += " ";
+		attrib->Print( 0, 0, &buffer );
+	}
+
+	if ( !element.FirstChild() ) 
+	{
+		buffer += " />";
+		DoLineBreak();
+	}
+	else 
+	{
+		buffer += ">";
+		if (    element.FirstChild()->ToText()
+			  && element.LastChild() == element.FirstChild()
+			  && element.FirstChild()->ToText()->CDATA() == false )
+		{
+			simpleTextPrint = true;
+			// no DoLineBreak()!
+		}
+		else
+		{
+			DoLineBreak();
+		}
+	}
+	++depth;	
+	return true;
+}
+
+
+bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
+{
+	--depth;
+	if ( !element.FirstChild() ) 
+	{
+		// nothing.
+	}
+	else 
+	{
+		if ( simpleTextPrint )
+		{
+			simpleTextPrint = false;
+		}
+		else
+		{
+			DoIndent();
+		}
+		buffer += "</";
+		buffer += element.Value();
+		buffer += ">";
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlText& text )
+{
+	if ( text.CDATA() )
+	{
+		DoIndent();
+		buffer += "<![CDATA[";
+		buffer += text.Value();
+		buffer += "]]>";
+		DoLineBreak();
+	}
+	else if ( simpleTextPrint )
+	{
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+	}
+	else
+	{
+		DoIndent();
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
+{
+	DoIndent();
+	declaration.Print( 0, 0, &buffer );
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlComment& comment )
+{
+	DoIndent();
+	buffer += "<!--";
+	buffer += comment.Value();
+	buffer += "-->";
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += unknown.Value();
+	buffer += ">";
+	DoLineBreak();
+	return true;
+}
+