This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| XML Class Factory Submitted by

Some time ago I started to wonder about the flexible capabilities of XML, but at the moment few game developers use it.
Talking about this matter with some others game developers I saw that some of them are expecting to use it in their new projects.
I wrote the class CClassFactory, that it's just a simple implementation of "something like a" class factory, using XML.
It wasn't made to be really useful, but just to show how flexible and easy it could be to make complex data relationships with xml, which makes it a great point for game developers because sometimes we really get mixed up with scripting, data, and so one.
This code could be extended further, with more features and perhaps with some scripting system that allows (in a easy way) to modify the context of the class factory, and so one.
In the source code you'll find : The class factory itself
ClassFactory.h
ClassFactory.cpp
A visual Studio 6 MFC Project that uses those classes to show the funcionality of the system. A directory called \doc with the documentation of the class in html and rtf format , thanks to Doxygen, a really great code doc tool. Note : CClassFactory uses tinyxml a great XML parser included in the project Juan Antonio Medina ^ mICrO

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/tinyxml/tinyxml.cpp] - (20,401 bytes)

    /*
    www.sourceforge.net/projects/tinyxml
    Original code (2.0 and earlier )copyright (c) 2000-2002 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
    damages arising from the use of this software.

    Permission is granted to anyone to use this software for any
    purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:

    1. The origin of this software must not be misrepresented; you must
    not claim that you wrote the original software. If you use this
    software in a product, an acknowledgment in the product documentation
    would be appreciated but is not required.

    2. Altered source versions must be plainly marked as such, and
    must not be misrepresented as being the original software.

    3. This notice may not be removed or altered from any source
    distribution.
    */
    #include "stdafx.h"
    #include <ctype.h>
    #include "tinyxml.h"

    bool TiXmlBase::condenseWhiteSpace = true;

    void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
    {
    	TIXML_STRING buffer;
    	PutString( str, &buffer );
    	(*stream) << buffer;
    }

    void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
    {
    	int i=0;

    	while( i<(int)str.length() )
    	{
    		int c = str[i];

    		if (    c == '&'
    		     && i < ( (int)str.length() - 2 )
    			 && str[i+1] == '#'
    			 && str[i+2] == 'x' )
    		{
    			// Hexadecimal character reference.
    			// Pass through unchanged.
    			// ©	-- copyright symbol, for example.
    			while ( i<(int)str.length() )
    			{
    				outString->append( str.c_str() + i, 1 );
    				++i;
    				if ( str[i] == ';' )
    					break;
    			}
    		}
    		else if ( c == '&' )
    		{
    			outString->append( entity[0].str, entity[0].strLength );
    			++i;
    		}
    		else if ( c == '<' )
    		{
    			outString->append( entity[1].str, entity[1].strLength );
    			++i;
    		}
    		else if ( c == '>' )
    		{
    			outString->append( entity[2].str, entity[2].strLength );
    			++i;
    		}
    		else if ( c == '\"' )
    		{
    			outString->append( entity[3].str, entity[3].strLength );
    			++i;
    		}
    		else if ( c == '\'' )
    		{
    			outString->append( entity[4].str, entity[4].strLength );
    			++i;
    		}
    		else if ( c < 32 || c > 126 )
    		{
    			// Easy pass at non-alpha/numeric/symbol
    			// 127 is the delete key. Below 32 is symbolic.
    			char buf[ 32 ];
    			sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
    			outString->append( buf, strlen( buf ) );
    			++i;
    		}
    		else
    		{
    			char realc = (char) c;
    			outString->append( &realc, 1 );
    			++i;
    		}
    	}
    }

    // <-- 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 )
    {
    	parent = 0;
    	type = _type;
    	firstChild = 0;
    	lastChild = 0;
    	prev = 0;
    	next = 0;
    	userData = 0;
    }

    TiXmlNode::~TiXmlNode()
    {
    	TiXmlNode* node = firstChild;
    	TiXmlNode* temp = 0;

    	while ( node )
    	{
    		temp = node;
    		node = node->next;
    		delete temp;
    	}
    }

    void TiXmlNode::Clear()
    {
    	TiXmlNode* node = firstChild;
    	TiXmlNode* temp = 0;

    	while ( node )
    	{
    		temp = node;
    		node = node->next;
    		delete temp;
    	}

    	firstChild = 0;
    	lastChild = 0;
    }

    TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
    {
    	node->parent = this;

    	node->prev = lastChild;
    	node->next = 0;

    	if ( lastChild )
    		lastChild->next = node;
    	else
    		firstChild = node;			// it was an empty list.

    	lastChild = node;
    	return node;
    }

    TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
    {
    	TiXmlNode* node = addThis.Clone();
    	if ( !node )
    		return 0;

    	return LinkEndChild( node );
    }

    TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
    {
    	if ( !beforeThis || beforeThis->parent != this )
    		return 0;

    	TiXmlNode* node = addThis.Clone();
    	if ( !node )
    		return 0;
    	node->parent = this;

    	node->next = beforeThis;
    	node->prev = beforeThis->prev;
    	if ( beforeThis->prev )
    	{
    		beforeThis->prev->next = node;
    	}
    	else
    	{
    		assert( firstChild == beforeThis );
    		firstChild = node;
    	}
    	beforeThis->prev = node;
    	return node;
    }

    TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
    {
    	if ( !afterThis || afterThis->parent != this )
    		return 0;

    	TiXmlNode* node = addThis.Clone();
    	if ( !node )
    		return 0;
    	node->parent = this;

    	node->prev = afterThis;
    	node->next = afterThis->next;
    	if ( afterThis->next )
    	{
    		afterThis->next->prev = node;
    	}
    	else
    	{
    		assert( lastChild == afterThis );
    		lastChild = node;
    	}
    	afterThis->next = node;
    	return node;
    }

    TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
    {
    	if ( replaceThis->parent != this )
    		return 0;

    	TiXmlNode* node = withThis.Clone();
    	if ( !node )
    		return 0;

    	node->next = replaceThis->next;
    	node->prev = replaceThis->prev;

    	if ( replaceThis->next )
    		replaceThis->next->prev = node;
    	else
    		lastChild = node;

    	if ( replaceThis->prev )
    		replaceThis->prev->next = node;
    	else
    		firstChild = node;

    	delete replaceThis;
    	node->parent = this;
    	return node;
    }

    bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
    {
    	if ( removeThis->parent != this )
    	{
    		assert( 0 );
    		return false;
    	}

    	if ( removeThis->next )
    		removeThis->next->prev = removeThis->prev;
    	else
    		lastChild = removeThis->prev;

    	if ( removeThis->prev )
    		removeThis->prev->next = removeThis->next;
    	else
    		firstChild = removeThis->next;

    	delete removeThis;
    	return true;
    }

    TiXmlNode* TiXmlNode::FirstChild( const char * value ) const
    {
    	TiXmlNode* node;
    	for ( node = firstChild; node; node = node->next )
    	{
    		if ( node->SValue() == TIXML_STRING( value ))
    			return node;
    	}
    	return 0;
    }

    TiXmlNode* TiXmlNode::LastChild( const char * value ) const
    {
    	TiXmlNode* node;
    	for ( node = lastChild; node; node = node->prev )
    	{
    		if ( node->SValue() == TIXML_STRING (value))
    			return node;
    	}
    	return 0;
    }

    TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
    {
    	if ( !previous )
    	{
    		return FirstChild();
    	}
    	else
    	{
    		assert( previous->parent == this );
    		return previous->NextSibling();
    	}
    }

    TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
    {
    	if ( !previous )
    	{
    		return FirstChild( val );
    	}
    	else
    	{
    		assert( previous->parent == this );
    		return previous->NextSibling( val );
    	}
    }

    TiXmlNode* TiXmlNode::NextSibling( const char * value ) const
    {
    	TiXmlNode* node;
    	for ( node = next; node; node = node->next )
    	{
    		if ( node->SValue() == TIXML_STRING (value))
    			return node;
    	}
    	return 0;
    }

    TiXmlNode* TiXmlNode::PreviousSibling( const char * value ) const
    {
    	TiXmlNode* node;
    	for ( node = prev; node; node = node->prev )
    	{
    		if ( node->SValue() == TIXML_STRING (value))
    			return node;
    	}
    	return 0;
    }

    void TiXmlElement::RemoveAttribute( const char * name )
    {
    	TiXmlAttribute* node = attributeSet.Find( name );
    	if ( node )
    	{
    		attributeSet.Remove( node );
    		delete node;
    	}
    }

    TiXmlElement* TiXmlNode::FirstChildElement() const
    {
    	TiXmlNode* node;

    	for (	node = FirstChild();
    	node;
    	node = node->NextSibling() )
    	{
    		if ( node->ToElement() )
    			return node->ToElement();
    	}
    	return 0;
    }

    TiXmlElement* TiXmlNode::FirstChildElement( const char * value ) const
    {
    	TiXmlNode* node;

    	for (	node = FirstChild( value );
    	node;
    	node = node->NextSibling( value ) )
    	{
    		if ( node->ToElement() )
    			return node->ToElement();
    	}
    	return 0;
    }

    TiXmlElement* TiXmlNode::NextSiblingElement() const
    {
    	TiXmlNode* node;

    	for (	node = NextSibling();
    	node;
    	node = node->NextSibling() )
    	{
    		if ( node->ToElement() )
    			return node->ToElement();
    	}
    	return 0;
    }

    TiXmlElement* TiXmlNode::NextSiblingElement( const char * value ) const
    {
    	TiXmlNode* node;

    	for (	node = NextSibling( value );
    	node;
    	node = node->NextSibling( value ) )
    	{
    		if ( node->ToElement() )
    			return node->ToElement();
    	}
    	return 0;
    }

    TiXmlDocument* TiXmlNode::GetDocument() const
    {
    	const 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 )
    {
    	firstChild = lastChild = 0;
    	value = _value;
    }

    TiXmlElement::~TiXmlElement()
    {
    	while( attributeSet.First() )
    	{
    		TiXmlAttribute* node = attributeSet.First();
    		attributeSet.Remove( node );
    		delete node;
    	}
    }

    const char * TiXmlElement::Attribute( const char * name ) const
    {
    	TiXmlAttribute* node = attributeSet.Find( name );

    	if ( node )
    		return node->Value();

    	return 0;
    }

    const char * TiXmlElement::Attribute( const char * name, int* i ) const
    {
    	const char * s = Attribute( name );
    	if ( i )
    	{
    		if ( s )
    			*i = atoi( s );
    		else
    			*i = 0;
    	}
    	return s;
    }

    void TiXmlElement::SetAttribute( const char * name, int val )
    {
    	char buf[64];
    	sprintf( buf, "%d", val );
    	SetAttribute( name, buf );
    }

    void TiXmlElement::SetAttribute( const char * name, const char * value )
    {
    	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 );
    	}
    }

    void TiXmlElement::Print( FILE* cfile, int depth ) const
    {
    	int i;
    	for ( i=0; i<depth; i++ )
    	{
    		fprintf( cfile, "    " );
    	}

    	fprintf( cfile, "<%s", value.c_str() );

    	TiXmlAttribute* attrib;
    	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
    	{
    		fprintf( cfile, " " );
    		attrib->Print( cfile, depth );
    	}

    	// There are 3 different formatting approaches:
    	// 1) An element without children is printed as a <foo /> node
    	// 2) An element with only a text child is printed as <foo> text </foo>
    	// 3) An element with children is printed on multiple lines.
    	TiXmlNode* node;
    	if ( !firstChild )
    	{
    		fprintf( cfile, " />" );
    	}
    	else if ( firstChild == lastChild && firstChild->ToText() )
    	{
    		fprintf( cfile, ">" );
    		firstChild->Print( cfile, depth + 1 );
    		fprintf( cfile, "</%s>", value.c_str() );
    	}
    	else
    	{
    		fprintf( cfile, ">" );

    		for ( node = firstChild; node; node=node->NextSibling() )
    		{
    			if ( !node->ToText() )
    			{
    				fprintf( cfile, "\n" );
    			}
    			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;

    	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 );
    		}
    		(*stream) << "</" << value << ">";
    	}
    	else
    	{
    		(*stream) << " />";
    	}
    }

    TiXmlNode* TiXmlElement::Clone() const
    {
    	TiXmlElement* clone = new TiXmlElement( Value() );
    	if ( !clone )
    		return 0;

    	CopyToClone( clone );

    	// Clone the attributes, then clone the children.
    	TiXmlAttribute* attribute = 0;
    	for(	attribute = attributeSet.First();
    	attribute;
    	attribute = attribute->Next() )
    	{
    		clone->SetAttribute( attribute->Name(), attribute->Value() );
    	}

    	TiXmlNode* node = 0;
    	for ( node = firstChild; node; node = node->NextSibling() )
    	{
    		clone->LinkEndChild( node->Clone() );
    	}
    	return clone;
    }

    TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
    {
    	error = false;
    	//	ignoreWhiteSpace = true;
    }

    TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
    {
    	//	ignoreWhiteSpace = true;
    	value = documentName;
    	error = false;
    }

    bool TiXmlDocument::LoadFile()
    {
    	// See STL_STRING_BUG below.
    	StringToBuffer buf( value );

    	if ( buf.buffer && LoadFile( buf.buffer ) )
    		return true;

    	return false;
    }

    bool TiXmlDocument::SaveFile() const
    {
    	// See STL_STRING_BUG below.
    	StringToBuffer buf( value );

    	if ( buf.buffer && SaveFile( buf.buffer ) )
    		return true;

    	return false;
    }

    bool TiXmlDocument::LoadFile( const char* filename )
    {
    	// Delete the existing data:
    	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;

    	FILE* file = fopen( value.c_str (), "r" );

    	if ( file )
    	{
    		// 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 );

    		const int BUF_SIZE = 2048;
    		char buf[BUF_SIZE];

    		while( fgets( buf, BUF_SIZE, file ) )
    		{
    			data += buf;
    		}
    		fclose( file );

    		Parse( data.c_str() );
    		if (  !Error() )
    		{
    			return true;
    		}
    	}
    	SetError( TIXML_ERROR_OPENING_FILE );
    	return false;
    }

    bool TiXmlDocument::SaveFile( const char * filename ) const
    {
    	// The old c stuff lives on...
    	FILE* fp = fopen( filename, "w" );
    	if ( fp )
    	{
    		Print( fp, 0 );
    		fclose( fp );
    		return true;
    	}
    	return false;
    }

    TiXmlNode* TiXmlDocument::Clone() const
    {
    	TiXmlDocument* clone = new TiXmlDocument();
    	if ( !clone )
    		return 0;

    	CopyToClone( clone );
    	clone->error = error;
    	clone->errorDesc = errorDesc.c_str ();

    	TiXmlNode* node = 0;
    	for ( node = firstChild; node; node = node->NextSibling() )
    	{
    		clone->LinkEndChild( node->Clone() );
    	}
    	return clone;
    }

    void TiXmlDocument::Print( FILE* cfile, int depth ) const
    {
    	TiXmlNode* node;
    	for ( node=FirstChild(); node; node=node->NextSibling() )
    	{
    		node->Print( cfile, depth );
    		fprintf( cfile, "\n" );
    	}
    }

    void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) 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;
    	}
    }

    TiXmlAttribute* TiXmlAttribute::Next() const
    {
    	// We are using knowledge of the sentinel. The sentinel
    	// have a value or name.
    	if ( next->value.empty() && next->name.empty() )
    		return 0;
    	return next;
    }

    TiXmlAttribute* TiXmlAttribute::Previous() const
    {
    	// We are using knowledge of the sentinel. The sentinel
    	// have a value or name.
    	if ( prev->value.empty() && prev->name.empty() )
    		return 0;
    	return prev;
    }

    void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
    {
    	TIXML_STRING n, v;

    	PutString( Name(), &n );
    	PutString( 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) << "'";
    	}
    	else
    	{
    		PutString( name, stream );
    		(*stream) << "=" << "\"";
    		PutString( value, stream );
    		(*stream) << "\"";
    	}
    }

    void TiXmlAttribute::SetIntValue( int value )
    {
    	char buf [64];
    	sprintf (buf, "%d", value);
    	SetValue (buf);
    }

    void TiXmlAttribute::SetDoubleValue( double value )
    {
    	char buf [64];
    	sprintf (buf, "%lf", value);
    	SetValue (buf);
    }

    const int TiXmlAttribute::IntValue() const
    {
    	return atoi (value.c_str ());
    }

    const double  TiXmlAttribute::DoubleValue() const
    {
    	return atof (value.c_str ());
    }

    void TiXmlComment::Print( FILE* cfile, int depth ) const
    {
    	for ( int i=0; i<depth; i++ )
    	{
    		fputs( "    ", cfile );
    	}
    	fprintf( cfile, "<!--%s-->", value.c_str() );
    }

    void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
    {
    	(*stream) << "<!--";
    	PutString( value, stream );
    	(*stream) << "-->";
    }

    TiXmlNode* TiXmlComment::Clone() const
    {
    	TiXmlComment* clone = new TiXmlComment();

    	if ( !clone )
    		return 0;

    	CopyToClone( clone );
    	return clone;
    }

    void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
    {
    	TIXML_STRING buffer;
    	PutString( value, &buffer );
    	fprintf( cfile, "%s", buffer.c_str() );
    }

    void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
    {
    	PutString( value, stream );
    }

    TiXmlNode* TiXmlText::Clone() const
    {
    	TiXmlText* clone = 0;
    	clone = new TiXmlText( "" );

    	if ( !clone )
    		return 0;

    	CopyToClone( clone );
    	return clone;
    }

    TiXmlDeclaration::TiXmlDeclaration( const char * _version,
    	const char * _encoding,
    	const char * _standalone )
    : TiXmlNode( TiXmlNode::DECLARATION )
    {
    	version = _version;
    	encoding = _encoding;
    	standalone = _standalone;
    }

    void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
    {
    	fprintf (cfile, "<?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 ( !encoding.empty() )
    	{
    		(*stream) << "encoding=\"";
    		PutString( encoding, stream );
    		(*stream ) << "\" ";
    	}
    	if ( !standalone.empty() )
    	{
    		(*stream) << "standalone=\"";
    		PutString( standalone, stream );
    		(*stream) << "\" ";
    	}
    	(*stream) << "?>";
    }

    TiXmlNode* TiXmlDeclaration::Clone() const
    {
    	TiXmlDeclaration* clone = new TiXmlDeclaration();

    	if ( !clone )
    		return 0;

    	CopyToClone( clone );
    	clone->version = version;
    	clone->encoding = encoding;
    	clone->standalone = standalone;
    	return clone;
    }

    void TiXmlUnknown::Print( FILE* cfile, int depth ) const
    {
    	for ( int i=0; i<depth; i++ )
    		fprintf( cfile, "    " );
    	fprintf( cfile, "%s", value.c_str() );
    }

    void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
    {
    	(*stream) << "<" << value << ">";		// Don't use entities hear! It is unknown.
    }

    TiXmlNode* TiXmlUnknown::Clone() const
    {
    	TiXmlUnknown* clone = new TiXmlUnknown();

    	if ( !clone )
    		return 0;

    	CopyToClone( clone );
    	return clone;
    }

    TiXmlAttributeSet::TiXmlAttributeSet()
    {
    	sentinel.next = &sentinel;
    	sentinel.prev = &sentinel;
    }

    TiXmlAttributeSet::~TiXmlAttributeSet()
    {
    	assert( sentinel.next == &sentinel );
    	assert( sentinel.prev == &sentinel );
    }

    void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
    {
    	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.

    	addMe->next = &sentinel;
    	addMe->prev = sentinel.prev;

    	sentinel.prev->next = addMe;
    	sentinel.prev      = addMe;
    }

    void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
    {
    	TiXmlAttribute* node;

    	for( node = sentinel.next; node != &sentinel; node = node->next )
    	{
    		if ( node == removeMe )
    		{
    			node->prev->next = node->next;
    			node->next->prev = node->prev;
    			node->next = 0;
    			node->prev = 0;
    			return;
    		}
    	}
    	assert( 0 );		// we tried to remove a non-linked attribute.
    }

    TiXmlAttribute*	TiXmlAttributeSet::Find( const char * name ) const
    {
    	TiXmlAttribute* node;

    	for( node = sentinel.next; node != &sentinel; node = node->next )
    	{
    		if ( node->name == name )
    			return node;
    	}
    	return 0;
    }

    #ifdef TIXML_USE_STL
    TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
    {
    	TIXML_STRING tag;
    	tag.reserve( 8 * 1000 );
    	base.StreamIn( &in, &tag );

    	base.Parse( tag.c_str() );
    	return in;
    }
    #endif

    TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
    {
    	base.StreamOut (& out);
    	return out;
    }

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/tinyxml/tinyxml.h] - (30,820 bytes)

    /*
    www.sourceforge.net/projects/tinyxml
    Original code (2.0 and earlier )copyright (c) 2000-2002 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
    damages arising from the use of this software.

    Permission is granted to anyone to use this software for any
    purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:

    1. The origin of this software must not be misrepresented; you must
    not claim that you wrote the original software. If you use this
    software in a product, an acknowledgment in the product documentation
    would be appreciated but is not required.

    2. Altered source versions must be plainly marked as such, and
    must not be misrepresented as being the original software.

    3. This notice may not be removed or altered from any source
    distribution.
    */

    #ifndef TINYXML_INCLUDED
    #define TINYXML_INCLUDED

    #ifdef _MSC_VER
    #pragma warning( disable : 4530 )
    #pragma warning( disable : 4786 )
    #endif

    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>

    // Help out windows:
    #if defined( _DEBUG ) && !defined( DEBUG )
    #define DEBUG
    #endif

    #if defined( DEBUG ) && defined( _MSC_VER )
    #include <windows.h>
    #define TIXML_LOG OutputDebugString
    #else
    #define TIXML_LOG printf
    #endif

    #ifdef TIXML_USE_STL
    	#include <string>
    	#define TIXML_STRING	std::string
    	#define TIXML_ISTREAM	std::istream
    	#define TIXML_OSTREAM	std::ostream
    #else
    	#include "tinystr.h"
    	#define TIXML_STRING	TiXmlString
    	#define TIXML_OSTREAM	TiXmlOutStream
    #endif

    class TiXmlDocument;
    class TiXmlElement;
    class TiXmlComment;
    class TiXmlUnknown;
    class TiXmlAttribute;
    class TiXmlText;
    class TiXmlDeclaration;

    /** TiXmlBase is a base class for every class in TinyXml.
    	It does little except to establish that TinyXml classes
    	can be printed and provide some utility functions.

    	In XML, the document and elements can contain
    	other elements and other types of nodes.

    	@verbatim
    	A Document can contain:	Element	(container or leaf)
    							Comment (leaf)
    							Unknown (leaf)
    							Declaration( leaf )

    	An Element can contain:	Element (container or leaf)
    							Text	(leaf)
    							Attributes (not on tree)
    							Comment (leaf)
    							Unknown (leaf)

    	A Decleration contains: Attributes (not on tree)
    	@endverbatim
    */
    class TiXmlBase
    {
    	friend class TiXmlNode;
    	friend class TiXmlElement;
    	friend class TiXmlDocument;

    public:
    	TiXmlBase()								{}
    	virtual ~TiXmlBase()					{}

    	/**	All TinyXml classes can print themselves to a filestream.
    		This is a formatted print, and will insert tabs and newlines.

    		(For an unformatted stream, use the << operator.)
    	*/
    	virtual void Print( FILE* cfile, int depth ) const = 0;

    	/**	The world does not agree on whether white space should be kept or
    		not. In order to make everyone happy, these global, static functions
    		are provided to set whether or not TinyXml will condense all white space
    		into a single space or not. The default is to condense. Note changing these
    		values is not thread safe.
    	*/
    	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }

    	/// Return the current white space setting.
    	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }

    protected:
    	// See STL_STRING_BUG
    	// Utility class to overcome a bug.
    	class StringToBuffer
    	{
    	  public:
    		StringToBuffer( const TIXML_STRING& str );
    		~StringToBuffer();
    		char* buffer;
    	};

    	static const char*	SkipWhiteSpace( const char* );
    	inline static bool	IsWhiteSpace( int c )		{ return ( isspace( c ) || c == '\n' || c == '\r' ); }

    	virtual void StreamOut (TIXML_OSTREAM *) const = 0;

    	#ifdef TIXML_USE_STL
    	    static bool	StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	    static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
    	#endif

    	/*	Reads an XML name into the string provided. Returns
    		a pointer just past the last character of the name,
    		or 0 if the function has an error.
    	*/
    	static const char* ReadName( const char* p, TIXML_STRING* name );

    	/*	Reads text. Returns a pointer past the given end tag.
    		Wickedly complex options, but it keeps the (sensitive) code in one place.
    	*/
    	static const char* ReadText(	const char* in,				// where to start
    									TIXML_STRING* text,			// the string read
    									bool ignoreWhiteSpace,		// whether to keep the white space
    									const char* endTag,			// what ends this text
    									bool ignoreCase );			// whether to ignore case in the end tag
    	virtual const char* Parse( const char* p ) = 0;

    	// If an entity has been found, transform it into a character.
    	static const char* GetEntity( const char* in, char* value );

    	// Get a character, while interpreting entities.
    	inline static const char* GetChar( const char* p, char* value )
    	{
    		assert( p );
    		if ( *p == '&' )
    		{
    			return GetEntity( p, value );
    		}
    		else
    		{
    			*value = *p;
    			return p+1;
    		}
    	}

    	// Puts a string to a stream, expanding entities as it goes.
    	// Note this should not contian the '<', '>', etc, or they will be transformed into entities!
    	static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );

    	static void PutString( const TIXML_STRING& str, TIXML_STRING* out );

    	// Return true if the next characters in the stream are any of the endTag sequences.
    	bool static StringEqual(	const char* p,
    								const char* endTag,
    								bool ignoreCase );

    	enum
    	{
    		TIXML_NO_ERROR = 0,
    		TIXML_ERROR,
    		TIXML_ERROR_OPENING_FILE,
    		TIXML_ERROR_OUT_OF_MEMORY,
    		TIXML_ERROR_PARSING_ELEMENT,
    		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
    		TIXML_ERROR_READING_ELEMENT_VALUE,
    		TIXML_ERROR_READING_ATTRIBUTES,
    		TIXML_ERROR_PARSING_EMPTY,
    		TIXML_ERROR_READING_END_TAG,
    		TIXML_ERROR_PARSING_UNKNOWN,
    		TIXML_ERROR_PARSING_COMMENT,
    		TIXML_ERROR_PARSING_DECLARATION,
    		TIXML_ERROR_DOCUMENT_EMPTY,

    		TIXML_ERROR_STRING_COUNT
    	};
    	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];

    private:
    	struct Entity
    	{
    		const char*     str;
    		unsigned int	strLength;
    		char		    chr;
    	};
    	enum
    	{
    		NUM_ENTITY = 5,
    		MAX_ENTITY_LENGTH = 6

    	};
    	static Entity entity[ NUM_ENTITY ];
    	static bool condenseWhiteSpace;
    };

    /** The parent class for everything in the Document Object Model.
    	(Except for attributes, which are contained in elements.)
    	Nodes have siblings, a parent, and children. A node can be
    	in a document, or stand on its own. The type of a TiXmlNode
    	can be queried, and it can be cast to its more defined type.
    */
    class TiXmlNode : public TiXmlBase
    {
    	friend class TiXmlDocument;
    	friend class TiXmlElement;

    public:
    	#ifdef TIXML_USE_STL

    	    /** An input stream operator, for every class. Tolerant of newlines and
    		    formatting, but doesn't expect them.
    	    */
    	    friend std::istream& operator >> (std::istream& in, TiXmlNode& base);

    	    /** An output stream operator, for every class. Note that this outputs
    		    without any newlines or formatting, as opposed to Print(), which
    		    includes tabs and new lines.

    		    The operator<< and operator>> are not completely symmetric. Writing
    		    a node to a stream is very well defined. You'll get a nice stream
    		    of output, without any extra whitespace or newlines.

    		    But reading is not as well defined. (As it always is.) If you create
    		    a TiXmlElement (for example) and read that from an input stream,
    		    the text needs to define an element or junk will result. This is
    		    true of all input streams, but it's worth keeping in mind.

    		    A TiXmlDocument will read nodes until it reads a root element.
    	    */
    	    friend std::ostream & operator<< (std::ostream& out, const TiXmlNode& base);

    	#else
    	    // Used internally, not part of the public API.
    	    friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
    	#endif

    	/** The types of XML nodes supported by TinyXml. (All the
    			unsupported types are picked up by UNKNOWN.)
    	*/
    	enum NodeType
    	{
    		DOCUMENT,
    		ELEMENT,
    		COMMENT,
    		UNKNOWN,
    		TEXT,
    		DECLARATION,
    		TYPECOUNT
    	};

    	virtual ~TiXmlNode();

    	/** The meaning of 'value' changes for the specific type of
    		TiXmlNode.
    		@verbatim
    		Document:	filename of the xml file
    		Element:	name of the element
    		Comment:	the comment text
    		Unknown:	the tag contents
    		Text:		the text string
    		@endverbatim

    		The subclasses will wrap this function.
    	*/
    	const char * Value () const { return value.c_str (); }

    	/** Changes the value of the node. Defined as:
    		@verbatim
    		Document:	filename of the xml file
    		Element:	name of the element
    		Comment:	the comment text
    		Unknown:	the tag contents
    		Text:		the text string
    		@endverbatim
    	*/
    	void SetValue (const char * _value) { value = _value;}

        #ifdef TIXML_USE_STL
    	/// STL std::string form.
    	void SetValue( const std::string& value )
    	{
    		StringToBuffer buf( value );
    		SetValue( buf.buffer ? buf.buffer : "" );
    	}
    	#endif

    	/// Delete all the children of this node. Does not affect 'this'.
    	void Clear();

    	/// One step up the DOM.
    	TiXmlNode* Parent() const					{ return parent; }

    	TiXmlNode* FirstChild()	const	{ return firstChild; }		///< The first child of this node. Will be null if there are no children.
    	TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.

    	TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
    	TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.

        #ifdef TIXML_USE_STL
    	TiXmlNode* FirstChild( const std::string& value ) const	{	return FirstChild (value.c_str ());	}	///< STL std::string form.
    	TiXmlNode* LastChild( const std::string& value ) const	{	return LastChild (value.c_str ());	}	///< STL std::string form.
    	#endif

    	/** An alternate way to walk the children of a node.
    		One way to iterate over nodes is:
    		@verbatim
    			for( child = parent->FirstChild(); child; child = child->NextSibling() )
    		@endverbatim

    		IterateChildren does the same thing with the syntax:
    		@verbatim
    			child = 0;
    			while( child = parent->IterateChildren( child ) )
    		@endverbatim

    		IterateChildren takes the previous child as input and finds
    		the next one. If the previous child is null, it returns the
    		first. IterateChildren will return null when done.
    	*/
    	TiXmlNode* IterateChildren( TiXmlNode* previous ) const;

    	/// This flavor of IterateChildren searches for children with a particular 'value'
    	TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const;

        #ifdef TIXML_USE_STL
    	TiXmlNode* IterateChildren( const std::string& value, TiXmlNode* previous ) const	{	return IterateChildren (value.c_str (), previous);	}	///< STL std::string form.
    	#endif

    	/** Add a new node related to this. Adds a child past the LastChild.
    		Returns a pointer to the new object or NULL if an error occured.
    	*/
    	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );

    	/** Add a new node related to this. Adds a child before the specified child.
    		Returns a pointer to the new object or NULL if an error occured.
    	*/
    	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );

    	/** Add a new node related to this. Adds a child after the specified child.
    		Returns a pointer to the new object or NULL if an error occured.
    	*/
    	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );

    	/** Replace a child of this node.
    		Returns a pointer to the new object or NULL if an error occured.
    	*/
    	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );

    	/// Delete a child of this node.
    	bool RemoveChild( TiXmlNode* removeThis );

    	/// Navigate to a sibling node.
    	TiXmlNode* PreviousSibling() const			{ return prev; }

    	/// Navigate to a sibling node.
    	TiXmlNode* PreviousSibling( const char * ) const;

        #ifdef TIXML_USE_STL
    	TiXmlNode* PreviousSibling( const std::string& value ) const	{	return PreviousSibling (value.c_str ());	}	///< STL std::string form.
    	TiXmlNode* NextSibling( const std::string& value) const	{	return NextSibling (value.c_str ());	}	///< STL std::string form.
    	#endif

    	/// Navigate to a sibling node.
    	TiXmlNode* NextSibling() const				{ return next; }

    	/// Navigate to a sibling node with the given 'value'.
    	TiXmlNode* NextSibling( const char * ) const;

    	/** Convenience function to get through elements.
    		Calls NextSibling and ToElement. Will skip all non-Element
    		nodes. Returns 0 if there is not another element.
    	*/
    	TiXmlElement* NextSiblingElement() const;

    	/** Convenience function to get through elements.
    		Calls NextSibling and ToElement. Will skip all non-Element
    		nodes. Returns 0 if there is not another element.
    	*/
    	TiXmlElement* NextSiblingElement( const char * ) const;

        #ifdef TIXML_USE_STL
    	TiXmlElement* NextSiblingElement( const std::string& value) const	{	return NextSiblingElement (value.c_str ());	}	///< STL std::string form.
    	#endif

    	/// Convenience function to get through elements.
    	TiXmlElement* FirstChildElement()	const;

    	/// Convenience function to get through elements.
    	TiXmlElement* FirstChildElement( const char * value ) const;

        #ifdef TIXML_USE_STL
    	TiXmlElement* FirstChildElement( const std::string& value ) const	{	return FirstChildElement (value.c_str ());	}	///< STL std::string form.
    	#endif

    	/// Query the type (as an enumerated value, above) of this node.
    	virtual int Type() const	{ return type; }

    	/** Return a pointer to the Document this node lives in.
    		Returns null if not in a document.
    	*/
    	TiXmlDocument* GetDocument() const;

    	/// Returns true if this node has no children.
    	bool NoChildren() const						{ return !firstChild; }

    	TiXmlDocument* ToDocument()	const		{ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    	TiXmlElement*  ToElement() const		{ return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    	TiXmlComment*  ToComment() const		{ return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    	TiXmlUnknown*  ToUnknown() const		{ return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    	TiXmlText*	   ToText()    const		{ return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    	TiXmlDeclaration* ToDeclaration() const	{ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.

    	virtual TiXmlNode* Clone() const = 0;

    	void  SetUserData( void* user )			{ userData = user; }
    	void* GetUserData()						{ return userData; }

    protected:
    	TiXmlNode( NodeType type );

    	#ifdef TIXML_USE_STL
    	    // The real work of the input operator.
    	    virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
    	#endif

    	// The node is passed in by ownership. This object will delete it.
    	TiXmlNode* LinkEndChild( TiXmlNode* addThis );

    	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
    	TiXmlNode* Identify( const char* start );
    	void CopyToClone( TiXmlNode* target ) const	{ target->SetValue (value.c_str() );
    												  target->userData = userData; }

    	// Internal Value function returning a TIXML_STRING
    	TIXML_STRING SValue() const	{ return value ; }

    	TiXmlNode*		parent;
    	NodeType		type;

    	TiXmlNode*		firstChild;
    	TiXmlNode*		lastChild;

    	TIXML_STRING	value;

    	TiXmlNode*		prev;
    	TiXmlNode*		next;
    	void*			userData;
    };

    /** An attribute is a name-value pair. Elements have an arbitrary
    	number of attributes, each with a unique name.

    	@note The attributes are not TiXmlNodes, since they are not
    		  part of the tinyXML document object model. There are other
    		  suggested ways to look at this problem.

    	@note Attributes have a parent
    */
    class TiXmlAttribute : public TiXmlBase
    {
    	friend class TiXmlAttributeSet;

    public:
    	/// Construct an empty attribute.
    	TiXmlAttribute() : prev( 0 ), next( 0 )	{}

    	#ifdef TIXML_USE_STL
    	/// std::string constructor.
    	TiXmlAttribute( const std::string& _name, const std::string& _value )
    	{
    		name = _name;
    		value = _value;
    	}
    	#endif

    	/// Construct an attribute with a name and value.
    	TiXmlAttribute( const char * _name, const char * _value ): name( _name ), value( _value ), prev( 0 ), next( 0 ) {}
    	const char*		Name()  const		{ return name.c_str (); }		///< Return the name of this attribute.
    	const char*		Value() const		{ return value.c_str (); }		///< Return the value of this attribute.
    	const int       IntValue() const;									///< Return the value of this attribute, converted to an integer.
    	const double	DoubleValue() const;								///< Return the value of this attribute, converted to a double.

    	void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
    	void SetValue( const char* _value )	{ value = _value; }				///< Set the value.

    	void SetIntValue( int value );										///< Set the value from an integer.
    	void SetDoubleValue( double value );								///< Set the value from a double.

        #ifdef TIXML_USE_STL
    	/// STL std::string form.
    	void SetName( const std::string& _name )
    	{
    		StringToBuffer buf( _name );
    		SetName ( buf.buffer ? buf.buffer : "error" );
    	}
    	/// STL std::string form.
    	void SetValue( const std::string& _value )
    	{
    		StringToBuffer buf( _value );
    		SetValue( buf.buffer ? buf.buffer : "error" );
    	}
    	#endif

    	/// Get the next sibling attribute in the DOM. Returns null at end.
    	TiXmlAttribute* Next() const;
    	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
    	TiXmlAttribute* Previous() const;

    	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
    	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
    	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }

    	/*	[internal use]
    		Attribtue parsing starts: first letter of the name
    						 returns: the next char after the value end quote
    	*/
    	virtual const char* Parse( const char* p );

    	// [internal use]
    	virtual void Print( FILE* cfile, int depth ) const;

    	virtual void StreamOut( TIXML_OSTREAM * out ) const;
    	// [internal use]
    	// Set the document pointer so the attribute can report errors.
    	void SetDocument( TiXmlDocument* doc )	{ document = doc; }

    private:
    	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
    	TIXML_STRING name;
    	TIXML_STRING value;
    	TiXmlAttribute*	prev;
    	TiXmlAttribute*	next;
    };

    /*	A class used to manage a group of attributes.
    	It is only used internally, both by the ELEMENT and the DECLARATION.

    	The set can be changed transparent to the Element and Declaration
    	classes that use it, but NOT transparent to the Attribute
    	which has to implement a next() and previous() method. Which makes
    	it a bit problematic and prevents the use of STL.

    	This version is implemented with circular lists because:
    		- I like circular lists
    		- it demonstrates some independence from the (typical) doubly linked list.
    */
    class TiXmlAttributeSet
    {
    public:
    	TiXmlAttributeSet();
    	~TiXmlAttributeSet();

    	void Add( TiXmlAttribute* attribute );
    	void Remove( TiXmlAttribute* attribute );

    	TiXmlAttribute* First() const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
    	TiXmlAttribute* Last()  const	{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
    	TiXmlAttribute*	Find( const char * name ) const;

    private:
    	TiXmlAttribute sentinel;
    };

    /** The element is a container class. It has a value, the element name,
    	and can contain other elements, text, comments, and unknowns.
    	Elements also contain an arbitrary number of attributes.
    */
    class TiXmlElement : public TiXmlNode
    {
    public:
    	/// Construct an element.
    	TiXmlElement (const char * in_value);

    	#ifdef TIXML_USE_STL
    	/// std::string constructor.
    	TiXmlElement( const std::string& _value ) : 	TiXmlNode( TiXmlNode::ELEMENT )
    	{
    		firstChild = lastChild = 0;
    		value = _value;
    	}
    	#endif

    	virtual ~TiXmlElement();

    	/** Given an attribute name, attribute returns the value
    		for the attribute of that name, or null if none exists.
    	*/
    	const char* Attribute( const char* name ) const;

    	/** Given an attribute name, attribute returns the value
    		for the attribute of that name, or null if none exists.
    		If the attribute exists and can be converted to an integer,
    		the integer value will be put in the return 'i', if 'i'
    		is non-null.
    	*/
    	const char* Attribute( const char* name, int* i ) const;

    	/** Sets an attribute of name to a given value. The attribute
    		will be created if it does not exist, or changed if it does.
    	*/
    	void SetAttribute( const char* name, const char * value );

        #ifdef TIXML_USE_STL
    	const char* Attribute( const std::string& name ) const				{ return Attribute( name.c_str() ); }
    	const char* Attribute( const std::string& name, int* i ) const		{ return Attribute( name.c_str(), i ); }

    	/// STL std::string form.
    	void SetAttribute( const std::string& name, const std::string& value )
    	{
    		StringToBuffer n( name );
    		StringToBuffer v( value );
    		if ( n.buffer && v.buffer )
    			SetAttribute (n.buffer, v.buffer );
    	}
    	///< STL std::string form.
    	void SetAttribute( const std::string& name, int value )
    	{
    		StringToBuffer n( name );
    		if ( n.buffer )
    			SetAttribute (n.buffer, value);
    	}
    	#endif

    	/** Sets an attribute of name to a given value. The attribute
    		will be created if it does not exist, or changed if it does.
    	*/
    	void SetAttribute( const char * name, int value );

    	/** Deletes an attribute with the given name.
    	*/
    	void RemoveAttribute( const char * name );
        #ifdef TIXML_USE_STL
    	void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
    	#endif

    	TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
    	TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.

    	// [internal use] Creates a new Element and returs it.
    	virtual TiXmlNode* Clone() const;
    	// [internal use]

    	virtual void Print( FILE* cfile, int depth ) const;

    protected:

    	// Used to be public [internal use]
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif
    	virtual void StreamOut( TIXML_OSTREAM * out ) const;

    	/*	[internal use]
    		Attribtue parsing starts: next char past '<'
    						 returns: next char past '>'
    	*/
    	virtual const char* Parse( const char* p );

    	/*	[internal use]
    		Reads the "value" of the element -- another element, or text.
    		This should terminate with the current end tag.
    	*/
    	const char* ReadValue( const char* in );

    private:
    	TiXmlAttributeSet attributeSet;
    };

    /**	An XML comment.
    */
    class TiXmlComment : public TiXmlNode
    {
    public:
    	/// Constructs an empty comment.
    	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
    	virtual ~TiXmlComment()	{}

    	// [internal use] Creates a new Element and returs it.
    	virtual TiXmlNode* Clone() const;
    	// [internal use]
    	virtual void Print( FILE* cfile, int depth ) const;
    protected:
    	// used to be public
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif
    	virtual void StreamOut( TIXML_OSTREAM * out ) const;
    	/*	[internal use]
    		Attribtue parsing starts: at the ! of the !--
    						 returns: next char past '>'
    	*/
    	virtual const char* Parse( const char* p );
    };

    /** XML text. Contained in an element.
    */
    class TiXmlText : public TiXmlNode
    {
    	friend class TiXmlElement;
    public:
    	/// Constructor.
    	TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
    	{
    		SetValue( initValue );
    	}
    	virtual ~TiXmlText() {}

    	#ifdef TIXML_USE_STL
    	/// Constructor.
    	TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
    	{
    		SetValue( initValue );
    	}
    	#endif

    protected :
    	// [internal use] Creates a new Element and returns it.
    	virtual TiXmlNode* Clone() const;
    	// [internal use]
    	virtual void Print( FILE* cfile, int depth ) const;
    	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
    	// [internal use]
    	bool Blank() const;	// returns true if all white space and new lines
    	/*	[internal use]
    			Attribtue parsing starts: First char of the text
    							 returns: next char past '>'
    		*/
    	virtual const char* Parse( const char* p );
    	// [internal use]
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif
    };

    /** In correct XML the declaration is the first entry in the file.
    	@verbatim
    		<?xml version="1.0" standalone="yes"?>
    	@endverbatim

    	TinyXml will happily read or write files without a declaration,
    	however. There are 3 possible attributes to the declaration:
    	version, encoding, and standalone.

    	Note: In this version of the code, the attributes are
    	handled as special cases, not generic attributes, simply
    	because there can only be at most 3 and they are always the same.
    */
    class TiXmlDeclaration : public TiXmlNode
    {
    public:
    	/// Construct an empty declaration.
    	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}

    #ifdef TIXML_USE_STL
    	/// Constructor.
    	TiXmlDeclaration(
    						const std::string& _version,
    						const std::string& _encoding,
    						const std::string& _standalone )
    					: TiXmlNode( TiXmlNode::DECLARATION )
    	{
    		version = _version;
    		encoding = _encoding;
    		standalone = _standalone;
    	}
    #endif

    	/// Construct.
    	TiXmlDeclaration::TiXmlDeclaration( const char * _version,
    										const char * _encoding,
    										const char * _standalone );

    	virtual ~TiXmlDeclaration()	{}

    	/// Version. Will return empty if none was found.
    	const char * Version() const		{ return version.c_str (); }
    	/// Encoding. Will return empty if none was found.
    	const char * Encoding() const		{ return encoding.c_str (); }
    	/// Is this a standalone document?
    	const char * Standalone() const		{ return standalone.c_str (); }

    	// [internal use] Creates a new Element and returs it.
    	virtual TiXmlNode* Clone() const;
    	// [internal use]
    	virtual void Print( FILE* cfile, int depth ) const;

    protected:
    	// used to be public
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif
    	virtual void StreamOut ( TIXML_OSTREAM * out) const;
    	//	[internal use]
    	//	Attribtue parsing starts: next char past '<'
    	//					 returns: next char past '>'

    	virtual const char* Parse( const char* p );

    private:
    	TIXML_STRING version;
    	TIXML_STRING encoding;
    	TIXML_STRING standalone;
    };

    /** Any tag that tinyXml doesn't recognize is save as an
    	unknown. It is a tag of text, but should not be modified.
    	It will be written back to the XML, unchanged, when the file
    	is saved.
    */
    class TiXmlUnknown : public TiXmlNode
    {
    public:
    	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
    	virtual ~TiXmlUnknown() {}

    	// [internal use]
    	virtual TiXmlNode* Clone() const;
    	// [internal use]
    	virtual void Print( FILE* cfile, int depth ) const;
    protected:
    	// used to be public
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif
    	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
    	/*	[internal use]
    		Attribute parsing starts: First char of the text
    						 returns: next char past '>'
    	*/
    	virtual const char* Parse( const char* p );
    };

    /** Always the top level node. A document binds together all the
    	XML pieces. It can be saved, loaded, and printed to the screen.
    	The 'value' of a document node is the xml file name.
    */
    class TiXmlDocument : public TiXmlNode
    {
    public:
    	/// Create an empty document, that has no name.
    	TiXmlDocument();
    	/// Create a document with a name. The name of the document is also the filename of the xml.
    	TiXmlDocument( const char * documentName );

    	#ifdef TIXML_USE_STL
    	/// Constructor.
    	TiXmlDocument( const std::string& documentName ) :
    	    TiXmlNode( TiXmlNode::DOCUMENT )
    	{
            value = documentName;
    		error = false;
    	}
    	#endif

    	virtual ~TiXmlDocument() {}

    	/** Load a file using the current document value.
    		Returns true if successful. Will delete any existing
    		document data before loading.
    	*/
    	bool LoadFile();
    	/// Save a file using the current document value. Returns true if successful.
    	bool SaveFile() const;
    	/// Load a file using the given filename. Returns true if successful.
    	bool LoadFile( const char * filename );
    	/// Save a file using the given filename. Returns true if successful.
    	bool SaveFile( const char * filename ) const;

    	#ifdef TIXML_USE_STL
    	bool LoadFile( const std::string& filename )			///< STL std::string version.
    	{
    		StringToBuffer f( filename );
    		return ( f.buffer && LoadFile( f.buffer ));
    	}
    	bool SaveFile( const std::string& filename ) const		///< STL std::string version.
    	{
    		StringToBuffer f( filename );
    		return ( f.buffer && SaveFile( f.buffer ));
    	}
    	#endif

    	/// Parse the given null terminated block of xml data.
    	virtual const char* Parse( const char* p );

    	/** Get the root element -- the only top level element -- of the document.
    		In well formed XML, there should only be one. TinyXml is tolerant of
    		multiple elements at the document level.
    	*/
    	TiXmlElement* RootElement() const		{ return FirstChildElement(); }

    	/// If, during parsing, a error occurs, Error will be set to true.
    	bool Error() const						{ return error; }

    	/// Contains a textual (english) description of the error if one occurs.
    	const char * ErrorDesc() const	{ return errorDesc.c_str (); }

    	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
    			prefer the ErrorId, this function will fetch it.
    		*/
    	const int ErrorId()	const				{ return errorId; }

    	/// If you have handled the error, it can be reset with this call.
    	void ClearError()						{ error = false; errorId = 0; errorDesc = ""; }

    	/** Dump the document to standard out. */
    	void Print() const						{ Print( stdout, 0 ); }

    	// [internal use]
    	virtual void Print( FILE* cfile, int depth = 0 ) const;
    	// [internal use]
    	void SetError( int err ) {		assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
    		error   = true;
    		errorId = err;
    	errorDesc = errorString[ errorId ]; }

    protected :
    	virtual void StreamOut ( TIXML_OSTREAM * out) const;
    	// [internal use]
    	virtual TiXmlNode* Clone() const;
    	#ifdef TIXML_USE_STL
    	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    	#endif

    private:
    	bool error;
    	int  errorId;
    	TIXML_STRING errorDesc;
    };

    #endif

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/tinyxml/tinyxmlerror.cpp] - (1,657 bytes)

    /*
    www.sourceforge.net/projects/tinyxml
    Original code (2.0 and earlier )copyright (c) 2000-2002 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
    damages arising from the use of this software.

    Permission is granted to anyone to use this software for any
    purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:

    1. The origin of this software must not be misrepresented; you must
    not claim that you wrote the original software. If you use this
    software in a product, an acknowledgment in the product documentation
    would be appreciated but is not required.

    2. Altered source versions must be plainly marked as such, and
    must not be misrepresented as being the original software.

    3. This notice may not be removed or altered from any source
    distribution.
    */
    #include "stdafx.h"
    #include "tinyxml.h"

    // The goal of the seperate error file is to make the first
    // step towards localization. tinyxml (currently) only supports
    // latin-1, but at least the error messages could now be translated.
    //
    // It also cleans up the code a bit.
    //

    const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
    {
    	"No error",
    	"Error",
    	"Failed to open file",
    	"Memory allocation failed.",
    	"Error parsing Element.",
    	"Failed to read Element name",
    	"Error reading Element value.",
    	"Error reading Attributes.",
    	"Error: empty tag.",
    	"Error reading end tag.",
    	"Error parsing Unknown.",
    	"Error parsing Comment.",
    	"Error parsing Declaration.",
    	"Error document empty."
    };

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/tinyxml/tinyxmlparser.cpp] - (18,440 bytes)

    /*
    www.sourceforge.net/projects/tinyxml
    Original code (2.0 and earlier )copyright (c) 2000-2002 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
    damages arising from the use of this software.

    Permission is granted to anyone to use this software for any
    purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:

    1. The origin of this software must not be misrepresented; you must
    not claim that you wrote the original software. If you use this
    software in a product, an acknowledgment in the product documentation
    would be appreciated but is not required.

    2. Altered source versions must be plainly marked as such, and
    must not be misrepresented as being the original software.

    3. This notice may not be removed or altered from any source
    distribution.
    */
    #include "stdafx.h"
    #include "tinyxml.h"
    #include <ctype.h>

    //#define DEBUG_PARSER

    // Note tha "PutString" hardcodes the same list. This
    // is less flexible than it appears. Changing the entries
    // or order will break putstring.
    TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
    {
    	{ "&",  5, '&' },
    	{ "<",   4, '<' },
    	{ ">",   4, '>' },
    	{ """, 6, '\"' },
    	{ "'", 6, '\'' }
    };

    const char* TiXmlBase::SkipWhiteSpace( const char* p )
    {
    	if ( !p || !*p )
    	{
    		return 0;
    	}
    	while ( p && *p )
    	{
    		if ( isspace( *p ) || *p == '\n' || *p =='\r' )		// Still using old rules for white space.
    			++p;
    		else
    			break;
    	}

    	return p;
    }

    #ifdef TIXML_USE_STL
    /*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	for( ;; )
    	{
    		if ( !in->good() ) return false;

    		int c = in->peek();
    		if ( !IsWhiteSpace( c ) )
    			return true;
    		*tag += in->get();
    	}
    }

    /*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag )
    {
    	while ( in->good() )
    	{
    		int c = in->peek();
    		if ( c == character )
    			return true;

    		in->get();
    		*tag += c;
    	}
    	return false;
    }
    #endif

    const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name )
    {
    	*name = "";
    	assert( p );

    	// Names start with letters or underscores.
    	// After that, they can be letters, underscores, numbers,
    	// hyphens, or colons. (Colons are valid ony for namespaces,
    	// but tinyxml can't tell namespaces from names.)
    	if (    p && *p
    		 && ( isalpha( (unsigned char) *p ) || *p == '_' ) )
    	{
    		while(		p && *p
    				&&	(		isalnum( (unsigned char ) *p )
    						 || *p == '_'
    						 || *p == '-'
    						 || *p == ':' ) )
    		{
    			(*name) += *p;
    			++p;
    		}
    		return p;
    	}
    	return 0;
    }

    const char* TiXmlBase::GetEntity( const char* p, char* value )
    {
    	// Presume an entity, and pull it out.
        TIXML_STRING ent;
    	int i;

    	// Ignore the &#x entities.
    	if (    strncmp( "&#x", p, 3 ) == 0
    	     && *(p+3)
    		 && *(p+4) )
    	{
    		*value = 0;

    		if ( isalpha( *(p+3) ) ) *value += ( tolower( *(p+3) ) - 'a' + 10 ) * 16;
    		else				     *value += ( *(p+3) - '0' ) * 16;

    		if ( isalpha( *(p+4) ) ) *value += ( tolower( *(p+4) ) - 'a' + 10 );
    		else				     *value += ( *(p+4) - '0' );

    		return p+6;
    	}

    	// Now try to match it.
    	for( i=0; i<NUM_ENTITY; ++i )
    	{
    		if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
    		{
    			assert( strlen( entity[i].str ) == entity[i].strLength );
    			*value = entity[i].chr;
    			return ( p + entity[i].strLength );
    		}
    	}

    	// So it wasn't an entity, its unrecognized, or something like that.
    	*value = *p;	// Don't put back the last one, since we return it!
    	return p+1;
    }

    bool TiXmlBase::StringEqual( const char* p,
    							 const char* tag,
    							 bool ignoreCase )
    {
    	assert( p );
    	if ( !p || !*p )
    	{
    		assert( 0 );
    		return false;
    	}

        if ( tolower( *p ) == tolower( *tag ) )
    	{
    		const char* q = p;

    		if (ignoreCase)
    		{
    			while ( *q && *tag && *q == *tag )
    			{
    				++q;
    				++tag;
    			}

    			if ( *tag == 0 )		// Have we found the end of the tag, and everything equal?
    			{
    				return true;
    			}
    		}
    		else
    		{
    			while ( *q && *tag && tolower( *q ) == tolower( *tag ) )
    			{
    				++q;
    				++tag;
    			}

    			if ( *tag == 0 )
    			{
    				return true;
    			}
    		}
    	}
    	return false;
    }

    const char* TiXmlBase::ReadText(	const char* p,
    									TIXML_STRING * text,
    									bool trimWhiteSpace,
    									const char* endTag,
    									bool caseInsensitive )
    {
        *text = "";
    	if (    !trimWhiteSpace			// certain tags always keep whitespace
    		 || !condenseWhiteSpace )	// if true, whitespace is always kept
    	{
    		// Keep all the white space.
    		while (	   p && *p
    				&& !StringEqual( p, endTag, caseInsensitive )
    			  )
    		{
    			char c;
    			p = GetChar( p, &c );
                (* text) += c;
    		}
    	}
    	else
    	{
    		bool whitespace = false;

    		// Remove leading white space:
    		p = SkipWhiteSpace( p );
    		while (	   p && *p
    				&& !StringEqual( p, endTag, caseInsensitive ) )
    		{
    			if ( *p == '\r' || *p == '\n' )
    			{
    				whitespace = true;
    				++p;
    			}
    			else if ( isspace( *p ) )
    			{
    				whitespace = true;
    				++p;
    			}
    			else
    			{
    				// If we've found whitespace, add it before the
    				// new character. Any whitespace just becomes a space.
    				if ( whitespace )
    				{
                   (* text) += ' ';
    					whitespace = false;
    				}
    				char c;
    				p = GetChar( p, &c );
                (* text) += c;
    			}
    		}
    	}
    	return p + strlen( endTag );
    }

    #ifdef TIXML_USE_STL

    void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	// The basic issue with a document is that we don't know what we're
    	// streaming. Read something presumed to be a tag (and hope), then
    	// identify it, and call the appropriate stream method on the tag.
    	//
    	// This "pre-streaming" will never read the closing ">" so the
    	// sub-tag can orient itself.

    	if ( !StreamTo( in, '<', tag ) )
    	{
    		SetError( TIXML_ERROR_PARSING_EMPTY );
    		return;
    	}

    	while ( in->good() )
    	{
    		int tagIndex = tag->length();
    		while ( in->good() && in->peek() != '>' )
    		{
    			int c = in->get();
    			(*tag) += (char) c;
    		}

    		if ( in->good() )
    		{
    			// We now have something we presume to be a node of
    			// some sort. Identify it, and call the node to
    			// continue streaming.
    			TiXmlNode* node = Identify( tag->c_str() + tagIndex );

    			if ( node )
    			{
    				node->StreamIn( in, tag );
    				bool isElement = node->ToElement() != 0;
    				delete node;
    				node = 0;

    				// If this is the root element, we're done. Parsing will be
    				// done by the >> operator.
    				if ( isElement )
    				{
    					return;
    				}
    			}
    			else
    			{
    				SetError( TIXML_ERROR );
    				return;
    			}
    		}
    	}
    	// We should have returned sooner.
    	SetError( TIXML_ERROR );
    }

    #endif

    const char* TiXmlDocument::Parse( const char* p )
    {
    	// Parse away, at the document level. Since a document
    	// contains nothing but other tags, most of what happens
    	// here is skipping white space.
    	//
    	// In this variant (as opposed to stream and Parse) we
    	// read everything we can.

    	if ( !p || !*p )
    	{
    		SetError( TIXML_ERROR_DOCUMENT_EMPTY );
    		return false;
    	}

        p = SkipWhiteSpace( p );
    	if ( !p )
    	{
    		SetError( TIXML_ERROR_DOCUMENT_EMPTY );
    		return false;
    	}

    	while ( p && *p )
    	{
    		TiXmlNode* node = Identify( p );
    		if ( node )
    		{
    			p = node->Parse( p );
    			LinkEndChild( node );
    		}
    		else
    		{
    			break;
    		}
    		p = SkipWhiteSpace( p );
    	}
    	// All is well.
    	return p;
    }

    TiXmlNode* TiXmlNode::Identify( const char* p )
    {
    	TiXmlNode* returnNode = 0;

    	p = SkipWhiteSpace( p );
    	if( !p || !*p || *p != '<' )
    	{
    		return 0;
    	}

    	TiXmlDocument* doc = GetDocument();
    	p = SkipWhiteSpace( p );

    	if ( !p || !*p )
    	{
    		return 0;
    	}

    	// What is this thing?
    	// - Elements start with a letter or underscore, but xml is reserved.
    	// - Comments: <!--
    	// - Decleration: <?xml
    	// - Everthing else is unknown to tinyxml.
    	//

    	const char* xmlHeader = { "<?xml" };
    	const char* commentHeader = { "<!--" };

    	if ( StringEqual( p, xmlHeader, true ) )
    	{
    		#ifdef DEBUG_PARSER
    			TIXML_LOG( "XML parsing Declaration\n" );
    		#endif
    		returnNode = new TiXmlDeclaration();
    	}
    	else if (    isalpha( *(p+1) )
    			  || *(p+1) == '_' )
    	{
    		#ifdef DEBUG_PARSER
    			TIXML_LOG( "XML parsing Element\n" );
    		#endif
    		returnNode = new TiXmlElement( "" );
    	}
    	else if ( StringEqual( p, commentHeader, false ) )
    	{
    		#ifdef DEBUG_PARSER
    			TIXML_LOG( "XML parsing Comment\n" );
    		#endif
    		returnNode = new TiXmlComment();
    	}
    	else
    	{
    		#ifdef DEBUG_PARSER
    			TIXML_LOG( "XML parsing Unknown\n" );
    		#endif
    		returnNode = new TiXmlUnknown();
    	}

    	if ( returnNode )
    	{
    		// Set the parent, so it can report errors
    		returnNode->parent = this;
    		//p = returnNode->Parse( p );
    	}
    	else
    	{
    		if ( doc )
    			doc->SetError( TIXML_ERROR_OUT_OF_MEMORY );
    	}
    	return returnNode;
    }

    #ifdef TIXML_USE_STL

    void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
    {
    	// We're called with some amount of pre-parsing. That is, some of "this"
    	// element is in "tag". Go ahead and stream to the closing ">"
    	while( in->good() )
    	{
    		int c = in->get();
    		(*tag) += (char) c ;

    		if ( c == '>' )
    			break;
    	}

    	if ( tag->length() < 3 ) return;

    	// Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
    	// If not, identify and stream.

    	if (    tag->at( tag->length() - 1 ) == '>'
    		 && tag->at( tag->length() - 2 ) == '/' )
    	{
    		// All good!
    		return;
    	}
    	else if ( tag->at( tag->length() - 1 ) == '>' )
    	{
    		// There is more. Could be:
    		//		text
    		//		closing tag
    		//		another node.
    		for ( ;; )
    		{
    			StreamWhiteSpace( in, tag );

    			// Do we have text?
    			if ( in->peek() != '<' )
    			{
    				// Yep, text.
    				TiXmlText text( "" );
    				text.StreamIn( in, tag );

    				// What follows text is a closing tag or another node.
    				// Go around again and figure it out.
    				continue;
    			}

    			// We now have either a closing tag...or another node.
    			// We should be at a "<", regardless.
    			if ( !in->good() ) return;
    			assert( in->peek() == '<' );
    			int tagIndex = tag->length();

    			bool closingTag = false;
    			bool firstCharFound = false;

    			for( ;; )
    			{
    				if ( !in->good() )
    					return;

    				int c = in->peek();

    				if ( c == '>' )
    					break;

    				*tag += c;
    				in->get();

    				if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
    				{
    					firstCharFound = true;
    					if ( c == '/' )
    						closingTag = true;
    				}
    			}
    			// If it was a closing tag, then read in the closing '>' to clean up the input stream.
    			// If it was not, the streaming will be done by the tag.
    			if ( closingTag )
    			{
    				int c = in->get();
    				assert( c == '>' );
    				*tag += c;

    				// We are done, once we've found our closing tag.
    				return;
    			}
    			else
    			{
    				// If not a closing tag, id it, and stream.
    				const char* tagloc = tag->c_str() + tagIndex;
    				TiXmlNode* node = Identify( tagloc );
    				if ( !node )
    					return;
    				node->StreamIn( in, tag );
    				delete node;
    				node = 0;

    				// No return: go around from the beginning: text, closing tag, or node.
    			}
    		}
    	}
    }
    #endif

    const char* TiXmlElement::Parse( const char* p )
    {
    	p = SkipWhiteSpace( p );
    	TiXmlDocument* document = GetDocument();

    	if ( !p || !*p || *p != '<' )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT );
    		return false;
    	}

    	p = SkipWhiteSpace( p+1 );

    	// Read the name.
        p = ReadName( p, &value );
    	if ( !p || !*p )
    	{
    		if ( document )	document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME );
    		return false;
    	}

        TIXML_STRING endTag ("</");
    	endTag += value;
    	endTag += ">";

    	// Check for and read attributes. Also look for an empty
    	// tag or an end tag.
    	while ( p && *p )
    	{
    		p = SkipWhiteSpace( p );
    		if ( !p || !*p )
    		{
    			if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
    			return 0;
    		}
    		if ( *p == '/' )
    		{
    			++p;
    			// Empty tag.
    			if ( *p  != '>' )
    			{
    				if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY );
    				return 0;
    			}
    			return (p+1);
    		}
    		else if ( *p == '>' )
    		{
    			// Done with attributes (if there were any.)
    			// Read the value -- which can include other
    			// elements -- read the end tag, and return.
    			++p;
    			p = ReadValue( p );		// Note this is an Element method, and will set the error if one happens.
    			if ( !p || !*p )
    				return 0;

    			// We should find the end tag now
    			if ( StringEqual( p, endTag.c_str(), false ) )
    			{
    				p += endTag.length();
    				return p;
    			}
    			else
    			{
    				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG );
    				return 0;
    			}
    		}
    		else
    		{
    			// Try to read an element:
    			TiXmlAttribute attrib;
    			attrib.SetDocument( document );
    			p = attrib.Parse( p );

    			if ( !p || !*p )
    			{
    				if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT );
    				return 0;
    			}
    			SetAttribute( attrib.Name(), attrib.Value() );
    		}
    	}
    	return p;
    }

    const char* TiXmlElement::ReadValue( const char* p )
    {
    	TiXmlDocument* document = GetDocument();

    	// Read in text and elements in any order.
    	p = SkipWhiteSpace( p );
    	while ( p && *p )
    	{
    		if ( *p != '<' )
    		{
    			// Take what we have, make a text element.
    			TiXmlText* textNode = new TiXmlText( "" );

    			if ( !textNode )
    			{
    				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
    				    return 0;
    			}

    			p = textNode->Parse( p );

    			if ( !textNode->Blank() )
    				LinkEndChild( textNode );
    			else
    				delete textNode;
    		}
    		else
    		{
    			// We hit a '<'
    			// Have we hit a new element or an end tag?
    			if ( StringEqual( p, "</", false ) )
    			{
    				return p;
    			}
    			else
    			{
    				TiXmlNode* node = Identify( p );
    				if ( node )
    				{
    					p = node->Parse( p );
    					LinkEndChild( node );
    				}
    				else
    				{
    					return 0;
    				}
    			}
    		}
    		p = SkipWhiteSpace( p );
    	}

    	if ( !p )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE );
    	}
    	return p;
    }

    #ifdef TIXML_USE_STL
    void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	while ( in->good() )
    	{
    		int c = in->get();
    		(*tag) += c;

    		if ( c == '>' )
    		{
    			// All is well.
    			return;
    		}
    	}
    }
    #endif

    const char* TiXmlUnknown::Parse( const char* p )
    {
    	TiXmlDocument* document = GetDocument();
    	p = SkipWhiteSpace( p );
    	if ( !p || !*p || *p != '<' )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN );
    		return 0;
    	}
    	++p;
        value = "";

    	while ( p && *p && *p != '>' )
    	{
    		value += *p;
    		++p;
    	}

    	if ( !p )
    	{
    		if ( document )	document->SetError( TIXML_ERROR_PARSING_UNKNOWN );
    	}
    	if ( *p == '>' )
    		return p+1;
    	return p;
    }

    #ifdef TIXML_USE_STL
    void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	while ( in->good() )
    	{
    		int c = in->get();
    		(*tag) += c;

    		if ( c == '>'
    			 && tag->at( tag->length() - 2 ) == '-'
    			 && tag->at( tag->length() - 3 ) == '-' )
    		{
    			// All is well.
    			return;
    		}
    	}
    }
    #endif

    const char* TiXmlComment::Parse( const char* p )
    {
    	TiXmlDocument* document = GetDocument();
    	value = "";

    	p = SkipWhiteSpace( p );
    	const char* startTag = "<!--";
    	const char* endTag   = "-->";

    	if ( !StringEqual( p, startTag, false ) )
    	{
    		document->SetError( TIXML_ERROR_PARSING_COMMENT );
    		return 0;
    	}
    	p += strlen( startTag );
    	p = ReadText( p, &value, false, endTag, false );
    	return p;
    }

    const char* TiXmlAttribute::Parse( const char* p )
    {
    	p = SkipWhiteSpace( p );
    	if ( !p || !*p ) return 0;

    	// Read the name, the '=' and the value.
    	p = ReadName( p, &name );
    	if ( !p || !*p )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
    		return 0;
    	}
    	p = SkipWhiteSpace( p );
    	if ( !p || !*p || *p != '=' )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
    		return 0;
    	}

    	++p;	// skip '='
    	p = SkipWhiteSpace( p );
    	if ( !p || !*p )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
    		return 0;
    	}

    	const char* end;

    	if ( *p == '\'' )
    	{
    		++p;
    		end = "\'";
    		p = ReadText( p, &value, false, end, false );
    	}
    	else if ( *p == '"' )
    	{
    		++p;
    		end = "\"";
    		p = ReadText( p, &value, false, end, false );
    	}
    	else
    	{
    		// All attribute values should be in single or double quotes.
    		// But this is such a common error that the parser will try
    		// its best, even without them.
    		value = "";
    		while (    p && *p										// existence
    				&& !isspace( *p ) && *p != '\n' && *p != '\r'	// whitespace
    				&& *p != '/' && *p != '>' )						// tag end
    		{
    			value += *p;
    			++p;
    		}
    	}
    	return p;
    }

    #ifdef TIXML_USE_STL
    void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	while ( in->good() )
    	{
    		int c = in->peek();
    		if ( c == '<' )
    			return;

    		(*tag) += c;
    		in->get();
    	}
    }
    #endif

    const char* TiXmlText::Parse( const char* p )
    {
    	value = "";

    	//TiXmlDocument* doc = GetDocument();
    	bool ignoreWhite = true;
    //	if ( doc && !doc->IgnoreWhiteSpace() ) ignoreWhite = false;

    	const char* end = "<";
    	p = ReadText( p, &value, ignoreWhite, end, false );
    	if ( p )
    		return p-1;	// don't truncate the '<'
    	return 0;
    }

    #ifdef TIXML_USE_STL
    void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
    {
    	while ( in->good() )
    	{
    		int c = in->get();
    		(*tag) += c;

    		if ( c == '>' )
    		{
    			// All is well.
    			return;
    		}
    	}
    }
    #endif

    const char* TiXmlDeclaration::Parse( const char* p )
    {
    	p = SkipWhiteSpace( p );
    	// Find the beginning, find the end, and look for
    	// the stuff in-between.
    	TiXmlDocument* document = GetDocument();
    	if ( !p || !*p || !StringEqual( p, "<?xml", true ) )
    	{
    		if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION );
    		return 0;
    	}

    	p += 5;
    //	const char* start = p+5;
    //	const char* end  = strstr( start, "?>" );

    	version = "";
    	encoding = "";
    	standalone = "";

    	while ( p && *p )
    	{
    		if ( *p == '>' )
    		{
    			++p;
    			return p;
    		}

    		p = SkipWhiteSpace( p );
    		if ( StringEqual( p, "version", true ) )
    		{
    //			p += 7;
    			TiXmlAttribute attrib;
    			p = attrib.Parse( p );
    			version = attrib.Value();
    		}
    		else if ( StringEqual( p, "encoding", true ) )
    		{
    //			p += 8;
    			TiXmlAttribute attrib;
    			p = attrib.Parse( p );
    			encoding = attrib.Value();
    		}
    		else if ( StringEqual( p, "standalone", true ) )
    		{
    //			p += 10;
    			TiXmlAttribute attrib;
    			p = attrib.Parse( p );
    			standalone = attrib.Value();
    		}
    		else
    		{
    			// Read over whatever it is.
    			while( p && *p && *p != '>' && !isspace( *p ) )
    				++p;
    		}
    	}
    	return 0;
    }

    bool TiXmlText::Blank() const
    {
    	for ( unsigned i=0; i<value.length(); i++ )
    		if ( !isspace( value[i] ) )
    			return false;
    	return true;
    }

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/ClassFactory.h] - (10,074 bytes)

    // ClassFactory.h: interface for the CClassFactory class.
    //
    //////////////////////////////////////////////////////////////////////

    #if !defined(XML_CLASS_FACTORY_INCLUDE)
    #define XML_CLASS_FACTORY_INCLUDE

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #include "tinyxml\tinyxml.h"

    /*!
       \author Juan Antonio Medina ^ mICrO ( mail<_at_>juan-medina.com )
       \mainpage Class Factorys using XML

       \section intro Introduction

      	Class Factorys using XML.

     	Forgive me for my really bad English :)

     	This class its a implementation of something like class factory.

     	It's could be easy modified to make father implementations of
     	complex data structures with an easy Access System.

     	It's could be easy modified to make father implementations of
     	complex data structures with an easy Access System.

       \section format Formats

     	XML Classes Definitions Format :
     	\verbatim
    	<classes>
    		<class name="className" extends="parentClass">
    			<attribute name="attriButeName"/>
    			...
    		</class>
    		...
    	</classes>
    	\endverbatim
    	Example :
    	\verbatim
    	<classes>
    		<class name="vehicle">
    			<attribute name="color"/>
    			<attribute name="model"/>
    			<attribute name="fabricant"/>
    		</class>
    		<class name="car" extends="vehicle">
    			<attribute name="wheels"/>
    			<attribute name="air-condition"/>
    		</class>
    		<class name="bus" extends="car">
    			<attribute name="paxes"/>
    		</class>
    		<class name="plane" extends="vehicle">
    			<attribute name="turbines"/>
    		</class>
    	</classes>
    	\endverbatim
    	XML Objects Instaces Context Format :
    	\verbatim
    	<instances>
    		<instance class="className" name="instaceName">
    			<attributeName>value</attributeName>
    			...
    		</instance>
    		...
    	</instances>
    	\endverbatim
    	Example :
    	\verbatim
    	<instances>
    		<instance class="car" name="car118256553">
    			<wheels>3</wheels>
    			<air-condition>no</air-condition>
    			<color>red</color>
    			<model>huge</model>
    			<fabricant />
    		</instance>
    		<instance class="bus" name="bus118260529">
    			<paxes>55</paxes>
    			<wheels>12</wheels>
    			<air-condition>yes</air-condition>
    			<color>blue</color>
    			<model />
    			<fabricant />
    		</instance>
    	</instances>
    	\endverbatim
     *
     */

    //!  Class Factorys using XML.
    /*!

    	This class its a implementation of something like class factory.

    */
    class CClassFactory
    {
    public:

    	/* INITIALIZATION ****/

    	//! Default constructor
    	/*!
    		Default constructor
    	*/
    	CClassFactory();

    	//! Default destructor
    	/*!
    		Default destructor
    	*/
    	virtual ~CClassFactory();

    	//! Clear current classes definitions
    	/*!
    		Clear current classes definitions
    	*/
    	void clearClasDef();

    	//! Clear current context
    	/*!
    		Clear current context
    	*/
    	void clearCurContext();

    	/* CLASS MANIPULATION ****/

    	//! add a new Class Definitions to the class Factory
    	/*!
    		You should call this method to add new Class Definition to the Class
    		Factory.

    		\param className = class name for the new class definition
    		\param extends = parent class, NULL if we dont set it
    		\return true if the operations was valid
    		\sa deleteClass
    		\sa findClass
    	*/
    	bool addClass (const char * className, const char* extends);

    	//! find a particular class in the clasess Definitions of the class Factory
    	/*!
    		You should call this method to find a class definition giving a class
    		name.

    		\param className = class name that you searching for

    		\return an TiXmlNode pointer represents the class, NULL if we couldn't
    		find it
    		\sa addClass
    		\sa deleteClass
    	*/
    	TiXmlNode* findClass(const char* className);

    	//! delete a particular class in the clasess Definitions
    	/*!
    		You should call this method to delete a class definition giving a class
    		name.

    		\param className = class name that you want to delete

    		\return true if the operations was valid
    		\sa addClass
    		\sa findClass
    	*/
    	bool deleteClass(const char* className);

    	/* ATTRIBUTE MANIPULATION ****/

    	//! add a new Attribute to a giving class
    	/*!
    		You should call this method to add a new attribute to a giving class.

    		\param className = class name that holds the attribute
    		\param attributeName = attribute name for the new attribute
    		\return true if the operations was valid
    		\sa deleteAttribute
    	*/
    	bool addAttribute(const char* className, const char* attributeName);

    	//! delete an Attribute from a giving class
    	/*!
    		You should call this method to delete an attribute from a giving class.

    		\param className = class name that holds the attribute
    		\param attributeName = attribute name for delete
    		\return true if the operations was valid
    		\sa addAttribute
    	*/
    	bool deleteAttribute(const char *className, const char *attributeName);

    	/* INSTANCE MANIPULATION ****/

    	//! Make a new object instace of a giving class name
    	/*!
    		You should call this method to add a new object instance of a giving
    		name. This method olso creates the values of the atributes of this
    		class, and uppers classes following the hirearchy..

    		\param className = class name that we want to instance it
    		\param instanceName = instance name for the new instance
    		\return true if the operations was valid
    		\sa deleteInstace
    		\sa findInstance
    	*/
    	bool newInstance(const char * className, const char* instanceName);

    	//! find an object instace of a giving class name
    	/*!
    		You should call this method to find an object instance of a giving
    		instace name.

    		\param instanceName = instance name to be find
    		\return an TiXmlNode pointer represents the instance, NULL if we
    		couldn't find it
    		\sa deleteInstace
    		\sa newInstance
    	*/
    	TiXmlNode* findInstance(const char * instanceName);

    	//! delete an object instace of a giving instance name
    	/*!
    		You should call this method to delete an object instance of a giving
    		instace name.

    		\param instanceName = instance name to be delete
    		\return true if the operations was valid
    		\sa newInstance
    		\sa findInstance
    	*/
    	bool deleteInstace(const char* instanceName);

    	//! Set the value of an attribute in a giving object instance
    	/*!
    		You should call this method to set the value of an attribute in a
    		givging object instace

    		\param instanceName = instance name of the object instance
    		\param attributeName = attribute name in the object instance
    		\param value = value to set
    		\return true if the operations was valid
    		\sa getValue

    	*/
    	bool setValue(const char * instanceName, const char* attributeName,
    		const char* value);

    	//! Get the value of an attribute in a giving object instance
    	/*!
    		You should call this method to get the value of an attribute in a
    		givging object instace

    		\param instanceName = instance name of the object instance
    		\param attributeName = attribute name in the object instance
    		\return the value of the attribute, "" if isn't have any
    		\sa setValue

    	*/
    	CString getValue(const char * instanceName, const char* attributeName);

    	/* PERSISTENCE ****/
    	//! Load classes definitions from a XML / Text file
    	/*!
    		You should call this method to load the full classes definitions
    		from a XML FILE

    		\param filename = file to load
    		\return true if operation it's valid
    		\sa saveClassDef

    	*/
    	bool loadClassDef(const char* filename);

    	//! Save classes definitions from a XML / Text file
    	/*!
    		You should call this method to save the full classes definitions
    		to a XML FILE

    		\param filename = file to save
    		\return true if operation it's valid
    		\sa loadClassDef

    	*/
    	bool saveClassDef(const char *filename);

    	//! Load object instances context from a XML / Text file
    	/*!
    		You should call this method to load the full object instances context
    		from a XML FILE

    		\param filename = file to load
    		\return true if operation it's valid
    		\sa saveContext

    	*/
    	bool loadContext(const char *filename);

    	//! Save object instances context from a XML / Text file
    	/*!
    		You should call this method to save the full object instances context
    		to a XML FILE

    		\param filename = file to save
    		\return true if operation it's valid
    		\sa loadContext

    	*/
    	bool saveContext(const char *filename);

    	/* GETs ****/

    	//! Get the full classes definitions as an xml dom document
    	/*!
    		You should call this method to get the classes definitions
    		in a TiXmlDocument.

    		\return an TiXmlDocument pointer to the classes definitions
    		\sa getCurContext

    	*/
    	inline TiXmlDocument* getClassDef(){return &classesDefinitions;}

    	//! Get the full objects instances as an xml dom document
    	/*!
    		You should call this method to get the objects instances
    		in a TiXmlDocument.

    		\return an TiXmlDocument pointer to the objects instances
    		\sa getClassDef

    	*/
    	inline TiXmlDocument* getCurContext(){return ¤tContext;}

    private:

    	/* ATTRIBUTES ****/

    	//! XML Document with classes definitions
    	/*!
    		XML Document with classes definitions
    	*/
    	TiXmlDocument classesDefinitions;

    	//! XML Document with objects instances
    	/*!
    		XML Document with objects instances
    	*/
    	TiXmlDocument currentContext;

    	/* HELPERS ****/

    	//! Add the attributes of a class to a instance (INTERNAL USE)
    	/*!
    		This function add the attributes of desired class to a giving
    		instance, this method work in recursive way to add all the
    		attribute of uppers classes to the instance.

    		\param element = TiXmlElement pointer represents the Instance
    		\param classNode = TiXmlElement pointer represents the class definition
    		\return true if operation it's valid
    	*/
    	bool addAttributesToInstance(TiXmlElement* element, TiXmlNode* classNode);

    	//! Display an Error Message
    	/*!
    		Nasty function to display errors
    		\param errorString = String with the error
    	*/
    	void error(char message[], ...);

    };

    #endif // !defined(XML_CLASS_FACTORY_INCLUDE)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewAttributeDlg.cpp] - (1,097 bytes)

    // NewAttributeDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "xmlclass.h"
    #include "NewAttributeDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CNewAttributeDlg dialog

    CNewAttributeDlg::CNewAttributeDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CNewAttributeDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CNewAttributeDlg)
    	m_attribute = _T("");
    	m_class = _T("");
    	//}}AFX_DATA_INIT
    }

    void CNewAttributeDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CNewAttributeDlg)
    	DDX_Text(pDX, IDC_ATTRIBUTE, m_attribute);
    	DDX_Text(pDX, IDC_CLASS, m_class);
    	//}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CNewAttributeDlg, CDialog)
    	//{{AFX_MSG_MAP(CNewAttributeDlg)
    		// NOTE: the ClassWizard will add message map macros here
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CNewAttributeDlg message handlers

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewAttributeDlg.h] - (1,302 bytes)

    #if !defined(AFX_NEWATTRIBUTEDLG_H__51538844_72C2_4F3C_B215_0B008681930F__INCLUDED_)
    #define AFX_NEWATTRIBUTEDLG_H__51538844_72C2_4F3C_B215_0B008681930F__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // NewAttributeDlg.h : header file
    //

    /////////////////////////////////////////////////////////////////////////////
    // CNewAttributeDlg dialog

    class CNewAttributeDlg : public CDialog
    {
    // Construction
    public:
    	CNewAttributeDlg(CWnd* pParent = NULL);   // standard constructor

    // Dialog Data
    	//{{AFX_DATA(CNewAttributeDlg)
    	enum { IDD = IDD_NEW_ATTRIBUTE };
    	CString	m_attribute;
    	CString	m_class;
    	//}}AFX_DATA

    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CNewAttributeDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL

    // Implementation
    protected:

    	// Generated message map functions
    	//{{AFX_MSG(CNewAttributeDlg)
    		// NOTE: the ClassWizard will add member functions here
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_NEWATTRIBUTEDLG_H__51538844_72C2_4F3C_B215_0B008681930F__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewClassDlg.cpp] - (1,043 bytes)

    // NewClassDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "xmlclass.h"
    #include "NewClassDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CNewClassDlg dialog

    CNewClassDlg::CNewClassDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CNewClassDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CNewClassDlg)
    	m_class = _T("");
    	m_extends = _T("");
    	//}}AFX_DATA_INIT
    }

    void CNewClassDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CNewClassDlg)
    	DDX_Text(pDX, IDC_CLASS, m_class);
    	DDX_Text(pDX, IDC_EXTENDS, m_extends);
    	//}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CNewClassDlg, CDialog)
    	//{{AFX_MSG_MAP(CNewClassDlg)
    		// NOTE: the ClassWizard will add message map macros here
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CNewClassDlg message handlers

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewClassDlg.h] - (1,256 bytes)

    #if !defined(AFX_NEWCLASSDLG_H__8E8966E7_4A62_4A42_9D0C_E77438BC5F64__INCLUDED_)
    #define AFX_NEWCLASSDLG_H__8E8966E7_4A62_4A42_9D0C_E77438BC5F64__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // NewClassDlg.h : header file
    //

    /////////////////////////////////////////////////////////////////////////////
    // CNewClassDlg dialog

    class CNewClassDlg : public CDialog
    {
    // Construction
    public:
    	CNewClassDlg(CWnd* pParent = NULL);   // standard constructor

    // Dialog Data
    	//{{AFX_DATA(CNewClassDlg)
    	enum { IDD = IDD_NEW_CLASS };
    	CString	m_class;
    	CString	m_extends;
    	//}}AFX_DATA

    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CNewClassDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL

    // Implementation
    protected:

    	// Generated message map functions
    	//{{AFX_MSG(CNewClassDlg)
    		// NOTE: the ClassWizard will add member functions here
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_NEWCLASSDLG_H__8E8966E7_4A62_4A42_9D0C_E77438BC5F64__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewInstanceDlg.cpp] - (1,070 bytes)

    // NewInstanceDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "xmlclass.h"
    #include "NewInstanceDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CNewInstanceDlg dialog

    CNewInstanceDlg::CNewInstanceDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CNewInstanceDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CNewInstanceDlg)
    	m_name = _T("");
    	m_class = _T("");
    	//}}AFX_DATA_INIT
    }

    void CNewInstanceDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CNewInstanceDlg)
    	DDX_Text(pDX, IDC_NAME, m_name);
    	DDX_Text(pDX, IDC_CLASS, m_class);
    	//}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CNewInstanceDlg, CDialog)
    	//{{AFX_MSG_MAP(CNewInstanceDlg)
    		// NOTE: the ClassWizard will add message map macros here
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CNewInstanceDlg message handlers

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/NewInstanceDlg.h] - (1,286 bytes)

    #if !defined(AFX_NewInstanceDlg_H__4D98A4B1_5E71_4C96_AA27_27B77A3F8FB0__INCLUDED_)
    #define AFX_NewInstanceDlg_H__4D98A4B1_5E71_4C96_AA27_27B77A3F8FB0__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // NewInstanceDlg.h : header file
    //

    /////////////////////////////////////////////////////////////////////////////
    // CNewInstanceDlg dialog

    class CNewInstanceDlg : public CDialog
    {
    // Construction
    public:
    	CNewInstanceDlg(CWnd* pParent = NULL);   // standard constructor

    // Dialog Data
    	//{{AFX_DATA(CNewInstanceDlg)
    	enum { IDD = IDD_NEW_INSTANCE };
    	CString	m_name;
    	CString	m_class;
    	//}}AFX_DATA

    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CNewInstanceDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL

    // Implementation
    protected:

    	// Generated message map functions
    	//{{AFX_MSG(CNewInstanceDlg)
    		// NOTE: the ClassWizard will add member functions here
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_NewInstanceDlg_H__4D98A4B1_5E71_4C96_AA27_27B77A3F8FB0__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/Resource.h] - (2,013 bytes)

    //{{NO_DEPENDENCIES}}
    // Microsoft Developer Studio generated include file.
    // Used by xmlclass.rc
    //
    #define IDM_ABOUTBOX                    0x0010
    #define IDD_ABOUTBOX                    100
    #define IDS_ABOUTBOX                    101
    #define IDD_XMLCLASS_DIALOG             102
    #define IDR_MAINFRAME                   128
    #define IDI_CLASS                       131
    #define IDI_CLASSES                     132
    #define IDD_NEW_INSTANCE                133
    #define IDI_ATTRIBUTE                   134
    #define IDI_INSTANCE                    135
    #define IDD_NEW_CLASS                   136
    #define IDD_NEW_ATTRIBUTE               137
    #define IDC_CLASSES_TREE                1000
    #define IDC_LOAD_CLASSES                1001
    #define IDC_CONTEXT_TREE                1002
    #define IDC_SAVE_CLASSES                1003
    #define IDC_LOAD_CONTEXT                1006
    #define IDC_SAVE_CONTEXT                1007
    #define IDC_NEW_INSTANCE                1010
    #define IDC_INSTANCE_NAME               1011
    #define IDC_ATTRIBUTE_NAME              1012
    #define IDC_VALUE                       1013
    #define IDC_DELETE_INSTANCE             1014
    #define IDC_NEW_CLASS                   1015
    #define IDC_SET_VALUE                   1016
    #define IDC_GET_VALUE                   1017
    #define IDC_QUIT                        1018
    #define IDC_CLASS                       1019
    #define IDC_NEW_ATTRIBUTE               1019
    #define IDC_NAME                        1020
    #define IDC_DELETE_CLASS                1020
    #define IDC_EXTENDS                     1021
    #define IDC_DELETE_ATTRIBUTE            1021
    #define IDC_ATTRIBUTE                   1022
    #define IDC_RICHEDIT1                   1023

    // Next default values for new objects
    //
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        139
    #define _APS_NEXT_COMMAND_VALUE         32771
    #define _APS_NEXT_CONTROL_VALUE         1025
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/StdAfx.cpp] - (210 bytes)

    // stdafx.cpp : source file that includes just the standard includes
    //	xmlclass.pch will be the pre-compiled header
    //	stdafx.obj will contain the pre-compiled type information

    #include "stdafx.h"

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/StdAfx.h] - (999 bytes)

    // stdafx.h : include file for standard system include files,
    //  or project specific include files that are used frequently, but
    //      are changed infrequently
    //

    #if !defined(AFX_STDAFX_H__136C542D_14E1_46C8_A874_D38F1C1DA66B__INCLUDED_)
    #define AFX_STDAFX_H__136C542D_14E1_46C8_A874_D38F1C1DA66B__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers

    #include <afxwin.h>         // MFC core and standard components
    #include <afxext.h>         // MFC extensions
    #include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
    #ifndef _AFX_NO_AFXCMN_SUPPORT
    #include <afxcmn.h>			// MFC support for Windows Common Controls
    #endif // _AFX_NO_AFXCMN_SUPPORT

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_STDAFX_H__136C542D_14E1_46C8_A874_D38F1C1DA66B__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/xmlclass.cpp] - (2,058 bytes)

    // xmlclass.cpp : Defines the class behaviors for the application.
    //

    #include "stdafx.h"
    #include "xmlclass.h"
    #include "xmlclassDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassApp

    BEGIN_MESSAGE_MAP(CXmlclassApp, CWinApp)
    	//{{AFX_MSG_MAP(CXmlclassApp)
    		// NOTE - the ClassWizard will add and remove mapping macros here.
    		//    DO NOT EDIT what you see in these blocks of generated code!
    	//}}AFX_MSG
    	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassApp construction

    CXmlclassApp::CXmlclassApp()
    {
    	// TODO: add construction code here,
    	// Place all significant initialization in InitInstance
    }

    /////////////////////////////////////////////////////////////////////////////
    // The one and only CXmlclassApp object

    CXmlclassApp theApp;

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassApp initialization

    BOOL CXmlclassApp::InitInstance()
    {
    	// Standard initialization
    	// If you are not using these features and wish to reduce the size
    	//  of your final executable, you should remove from the following
    	//  the specific initialization routines you do not need.

    #ifdef _AFXDLL
    	Enable3dControls();			// Call this when using MFC in a shared DLL
    #else
    	Enable3dControlsStatic();	// Call this when linking to MFC statically
    #endif

    	CXmlclassDlg dlg;
    	m_pMainWnd = &dlg;
    	int nResponse = dlg.DoModal();
    	if (nResponse == IDOK)
    	{
    		// TODO: Place code here to handle when the dialog is
    		//  dismissed with OK
    	}
    	else if (nResponse == IDCANCEL)
    	{
    		// TODO: Place code here to handle when the dialog is
    		//  dismissed with Cancel
    	}

    	// Since the dialog has been closed, return FALSE so that we exit the
    	//  application, rather than start the application's message pump.
    	return FALSE;
    }

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/xmlclass.h] - (1,346 bytes)

    // xmlclass.h : main header file for the XMLCLASS application
    //

    #if !defined(AFX_XMLCLASS_H__932E6872_4D2A_42C9_9056_AF38D9B0CA06__INCLUDED_)
    #define AFX_XMLCLASS_H__932E6872_4D2A_42C9_9056_AF38D9B0CA06__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #ifndef __AFXWIN_H__
    	#error include 'stdafx.h' before including this file for PCH
    #endif

    #include "resource.h"		// main symbols

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassApp:
    // See xmlclass.cpp for the implementation of this class
    //

    class CXmlclassApp : public CWinApp
    {
    public:
    	CXmlclassApp();

    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CXmlclassApp)
    	public:
    	virtual BOOL InitInstance();
    	//}}AFX_VIRTUAL

    // Implementation

    	//{{AFX_MSG(CXmlclassApp)
    		// NOTE - the ClassWizard will add and remove member functions here.
    		//    DO NOT EDIT what you see in these blocks of generated code !
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };

    /////////////////////////////////////////////////////////////////////////////

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_XMLCLASS_H__932E6872_4D2A_42C9_9056_AF38D9B0CA06__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/xmlclassDlg.cpp] - (15,435 bytes)

    // xmlclassDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "xmlclass.h"
    #include "xmlclassDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CAboutDlg dialog used for App About

    class CAboutDlg : public CDialog
    {
    public:
    	CAboutDlg();

    // Dialog Data
    	//{{AFX_DATA(CAboutDlg)
    	enum { IDD = IDD_ABOUTBOX };
    	//}}AFX_DATA

    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CAboutDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL

    // Implementation
    protected:
    	//{{AFX_MSG(CAboutDlg)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };

    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    	//{{AFX_DATA_INIT(CAboutDlg)
    	//}}AFX_DATA_INIT
    }

    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CAboutDlg)
    	//}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    	//{{AFX_MSG_MAP(CAboutDlg)
    		// No message handlers
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassDlg dialog

    CXmlclassDlg::CXmlclassDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CXmlclassDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CXmlclassDlg)
    	m_instanceName = _T("");
    	m_attributeName = _T("");
    	m_value = _T("");
    	//}}AFX_DATA_INIT
    	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }

    void CXmlclassDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CXmlclassDlg)
    	DDX_Control(pDX, IDC_DELETE_ATTRIBUTE, m_bDeleteAttribute);
    	DDX_Control(pDX, IDC_DELETE_CLASS, m_bDeleteClass);
    	DDX_Control(pDX, IDC_NEW_ATTRIBUTE, m_bNewAttribute);
    	DDX_Control(pDX, IDC_DELETE_INSTANCE, m_bDeleteInstance);
    	DDX_Control(pDX, IDC_CONTEXT_TREE, m_contextTree);
    	DDX_Control(pDX, IDC_NEW_INSTANCE, m_bNewInstance);
    	DDX_Control(pDX, IDC_CLASSES_TREE, m_classTree);
    	DDX_Text(pDX, IDC_INSTANCE_NAME, m_instanceName);
    	DDX_Text(pDX, IDC_ATTRIBUTE_NAME, m_attributeName);
    	DDX_Text(pDX, IDC_VALUE, m_value);
    	//}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CXmlclassDlg, CDialog)
    	//{{AFX_MSG_MAP(CXmlclassDlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDC_QUIT, OnQuit)
    	ON_BN_CLICKED(IDC_LOAD_CLASSES, OnLoadClasses)
    	ON_NOTIFY(TVN_SELCHANGED, IDC_CLASSES_TREE, OnSelchangedClassesTree)
    	ON_BN_CLICKED(IDC_NEW_INSTANCE, OnNewInstance)
    	ON_NOTIFY(TVN_SELCHANGED, IDC_CONTEXT_TREE, OnSelchangedContextTree)
    	ON_BN_CLICKED(IDC_DELETE_INSTANCE, OnDeleteInstance)
    	ON_BN_CLICKED(IDC_SET_VALUE, OnSetValue)
    	ON_BN_CLICKED(IDC_GET_VALUE, OnGetValue)
    	ON_NOTIFY(NM_DBLCLK, IDC_CONTEXT_TREE, OnDblclkContextTree)
    	ON_BN_CLICKED(IDC_SAVE_CLASSES, OnSaveClasses)
    	ON_BN_CLICKED(IDC_LOAD_CONTEXT, OnLoadContext)
    	ON_BN_CLICKED(IDC_SAVE_CONTEXT, OnSaveContext)
    	ON_BN_CLICKED(IDC_NEW_CLASS, OnNewClass)
    	ON_BN_CLICKED(IDC_NEW_ATTRIBUTE, OnNewAttribute)
    	ON_BN_CLICKED(IDC_DELETE_CLASS, OnDeleteClass)
    	ON_BN_CLICKED(IDC_DELETE_ATTRIBUTE, OnDeleteAttribute)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassDlg message handlers

    BOOL CXmlclassDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();

    	// Add "About..." menu item to system menu.

    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);

    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}

    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	//SetIcon(m_hIcon, FALSE);		// Set small icon

    	initControls();

    	return TRUE;  // return TRUE  unless you set the focus to a control
    }

    void CXmlclassDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }

    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.

    void CXmlclassDlg::OnPaint()
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting

    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;

    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    	}
    }

    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CXmlclassDlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }

    void CXmlclassDlg::OnQuit()
    {
    	EndDialog(IDOK);
    }

    void CXmlclassDlg::initControls()
    {

    	m_classDefImages.Create(16,16,ILC_MASK,0,5);
    	m_classDefImages.Add(AfxGetApp()->LoadIcon(IDI_CLASSES));
    	m_classDefImages.Add(AfxGetApp()->LoadIcon(IDI_CLASS));

    	m_contextImages.Create(16,16,ILC_MASK,0,5);
    	m_contextImages.Add(AfxGetApp()->LoadIcon(IDI_INSTANCE));
    	m_contextImages.Add(AfxGetApp()->LoadIcon(IDI_ATTRIBUTE));

    	m_classTree.SetImageList(&m_classDefImages,TVSIL_NORMAL);
    	m_contextTree.SetImageList(&m_contextImages,TVSIL_NORMAL);

    	classFactory.clearClasDef();
    	classFactory.clearCurContext();

    	resetUI();
    }

    void CXmlclassDlg::OnLoadClasses()
    {
    	CFileDialog fileDialog(true,".xml","classes.xml",OFN_HIDEREADONLY,"Xml Class definitions Files (*.xml)|*.xml|All Files (*.*)|*.*||");

    	if ( fileDialog.DoModal()==IDOK){
    		if ( classFactory.loadClassDef((LPCTSTR )fileDialog.GetPathName()) ) {

    			DrawClasses(classFactory.getClassDef()->RootElement());
    		}
    	}
    }

    void CXmlclassDlg::DrawClasses(TiXmlElement *classes)
    {
    	resetUI();

    	if (classes==NULL) return;

    	char strBuf[1024];

    	TiXmlNode* classNode = NULL;
    	TiXmlNode* attributeNode = NULL;

    	const char* className=NULL;
    	const char* attributeName=NULL;
    	const char* extends=NULL;

    	classNode = classes->FirstChild("class");

    	while (classNode!=NULL){

    		className = classNode->ToElement()->Attribute("name");
    		extends = classNode->ToElement()->Attribute("extends");

    		if (className==NULL){
    			MessageBox("Error parsing class definition. Class need a name","Error",MB_OK|MB_ICONEXCLAMATION);
    		}else{
    			if (extends==NULL){
    				wsprintf (strBuf, "class : %s", className);
    			}else{
    				wsprintf (strBuf, "class : %s <extend %s>", className,extends);
    			}
    			HTREEITEM  classInTree = m_classTree.InsertItem(strBuf,0);

    			attributeNode = classNode->FirstChild("attribute");

    			while ( attributeNode!=NULL){

    				attributeName = attributeNode->ToElement()->Attribute("name");

    				if (attributeName==NULL){
    					MessageBox("Error parsing class definition. Atribute need a name","Error",MB_OK|MB_ICONEXCLAMATION);
    				}else{

    					wsprintf (strBuf, "attribute : %s", attributeName);
    					m_classTree.InsertItem(strBuf,1,1,classInTree);
    				}

    				attributeNode = attributeNode->NextSibling("attribute");
    			}
    		}

    		classNode = classNode->NextSibling("class");
    	}
    }

    void CXmlclassDlg::OnSelchangedClassesTree(NMHDR* pNMHDR, LRESULT* pResult)
    {
    	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

    	CString selected =m_classTree.GetItemText(pNMTreeView->itemNew.hItem);

    	BOOL itsClass  = (selected.Find("class")!=-1);

    	m_bNewInstance.EnableWindow(itsClass);
    	m_bNewAttribute.EnableWindow(itsClass);

    	m_bDeleteAttribute.EnableWindow(!itsClass);
    	m_bDeleteClass.EnableWindow(itsClass);

    	*pResult = 0;
    }

    void CXmlclassDlg::OnNewInstance()
    {

    	CString selected = m_classTree.GetItemText(m_classTree.GetSelectedItem());

    	int pos = selected.Find(":");

    	if (pos!=-1){
    		selected = selected.Mid(pos+2);

    		pos = selected.Find("<");

    		if (pos!=-1)
    			selected = selected.Left(pos-1);

    		newInstanceDlg.m_class = selected;

    		selected.Format("%s%08d",selected,GetTickCount());
    		newInstanceDlg.m_name = selected;

    		if ( newInstanceDlg.DoModal() == IDOK)
    		{
    			if ( classFactory.newInstance(newInstanceDlg.m_class,newInstanceDlg.m_name) )
    			{
    				DrawContext(classFactory.getCurContext()->RootElement());
    			}
    		}

    	}

    }

    void CXmlclassDlg::resetUI()
    {
    	m_classTree.DeleteAllItems();
    	m_bNewInstance.EnableWindow(false);
    	m_bDeleteInstance.EnableWindow(false);
    	m_bNewAttribute.EnableWindow(false);
    	m_bDeleteAttribute.EnableWindow(false);
    	m_bDeleteClass.EnableWindow(false);
    }

    void CXmlclassDlg::DrawContext(TiXmlElement *context)
    {
    	m_contextTree.DeleteAllItems();

    	if (context==NULL) return;

    	char strBuf[1024];

    	TiXmlNode* instanceNode = NULL;
    	TiXmlNode* attributeNode = NULL;

    	const char* instanceName=NULL;
    	const char* className=NULL;

    	instanceNode = context->FirstChild("instance");

    	while (instanceNode!=NULL){

    		instanceName = instanceNode->ToElement()->Attribute("name");
    		className = instanceNode->ToElement()->Attribute("class");

    		if (instanceName==NULL){
    			MessageBox("Error parsing instance, instance need a name","Error",MB_OK|MB_ICONEXCLAMATION);
    		}else{
    			wsprintf (strBuf, "%s : <class %s>", instanceName,className);
    			HTREEITEM  instanceInTree = m_contextTree.InsertItem(strBuf,0);

    			attributeNode = instanceNode->FirstChild();

    			while ( attributeNode!=NULL){

    				wsprintf (strBuf, "%s", attributeNode->Value());
    				m_contextTree.InsertItem(strBuf,1,1,instanceInTree);

    				attributeNode = attributeNode->NextSibling();
    			}
    		}

    		instanceNode = instanceNode->NextSibling("instance");
    	}
    }

    void CXmlclassDlg::OnSelchangedContextTree(NMHDR* pNMHDR, LRESULT* pResult)
    {
    	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

    	CString selected = m_classTree.GetItemText(pNMTreeView->itemNew.hItem);

    	BOOL itsInstance  = (selected.Find("class")!=-1);

    	m_bDeleteInstance.EnableWindow(itsInstance);

    	*pResult = 0;
    }

    void CXmlclassDlg::OnDeleteInstance()
    {
    	CString selected = m_contextTree.GetItemText(m_contextTree.GetSelectedItem());

    	int pos = selected.Find(":");

    	if (pos!=-1){
    		selected = selected.Left(pos-1);
    		if ( classFactory.deleteInstace(selected) )
    		{
    			DrawContext(classFactory.getCurContext()->RootElement());
    		}

    	}

    }

    void CXmlclassDlg::OnSetValue()
    {
    	UpdateData(TRUE);
    	classFactory.setValue(m_instanceName,m_attributeName,m_value);

    }

    void CXmlclassDlg::OnGetValue()
    {
    	UpdateData(TRUE);
    	m_value = classFactory.getValue(m_instanceName,m_attributeName);
    	UpdateData(FALSE);
    }

    void CXmlclassDlg::OnDblclkContextTree(NMHDR* pNMHDR, LRESULT* pResult)
    {
    	HTREEITEM  item, parentitem;

    	item = m_contextTree.GetSelectedItem();
    	parentitem = m_contextTree.GetParentItem(item);

    	CString selected;

    	selected =  m_contextTree.GetItemText(item);
    	SetObjectInstaceData(selected);

    	selected =  m_contextTree.GetItemText(parentitem);
    	SetObjectInstaceData(selected);

    	if (parentitem !=NULL){
    		OnGetValue();
    	}

    	*pResult = 0;
    }

    void CXmlclassDlg::SetObjectInstaceData(CString data)
    {
    	int pos =  data.Find(":");
    	if (pos!=-1){
    		data = data.Left(pos-1);
    		m_instanceName = data;
    	}else{
    		m_attributeName = data;
    	}

    	UpdateData(FALSE);
    }

    void CXmlclassDlg::OnSaveClasses()
    {
    	CFileDialog fileDialog(false,".xml","classes.xml",OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT,"Xml Class definitions Files (*.xml)|*.xml|All Files (*.*)|*.*||");

    	if ( fileDialog.DoModal()==IDOK){
    		classFactory.saveClassDef((LPCTSTR )fileDialog.GetPathName());
    	}

    }

    void CXmlclassDlg::OnLoadContext()
    {
    	CFileDialog fileDialog(true,".xml","context.xml",OFN_HIDEREADONLY,"Xml Context Files (*.xml)|*.xml|All Files (*.*)|*.*||");

    	if ( fileDialog.DoModal()==IDOK){
    		if ( classFactory.loadContext((LPCTSTR )fileDialog.GetPathName()) ) {
    			DrawContext(classFactory.getCurContext()->RootElement());
    		}
    	}

    }

    void CXmlclassDlg::OnSaveContext()
    {
    	CFileDialog fileDialog(false,".xml","context.xml",OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT,"Xml Context Files (*.xml)|*.xml|All Files (*.*)|*.*||");

    	if ( fileDialog.DoModal()==IDOK){
    		classFactory.saveContext((LPCTSTR )fileDialog.GetPathName());
    	}

    }

    void CXmlclassDlg::OnNewClass()
    {
    		if ( newClassDlg.DoModal() == IDOK)
    		{
    			if (classFactory.addClass(newClassDlg.m_class,newClassDlg.m_extends))
    			{
    				DrawClasses(classFactory.getClassDef()->RootElement());
    			}
    		}

    }

    void CXmlclassDlg::OnNewAttribute()
    {

    	CString selected = m_classTree.GetItemText(m_classTree.GetSelectedItem());

    	int pos = selected.Find(":");

    	if (pos!=-1){
    		selected = selected.Mid(pos+2);

    		pos = selected.Find("<");

    		if (pos!=-1)
    			selected = selected.Left(pos-1);

    		newAttributeDlg.m_class = selected;

    		if ( newAttributeDlg.DoModal() == IDOK)
    		{
    			if (classFactory.addAttribute(newAttributeDlg.m_class,newAttributeDlg.m_attribute))
    			{
    				DrawClasses(classFactory.getClassDef()->RootElement());
    			}

    		}

    	}

    }

    void CXmlclassDlg::OnDeleteClass()
    {
    	if ( MessageBox("Deleting a class dosen't delete current instance of this/descents classes.\nThis operation either delete descent class definitions.\n\nDo you really want to delete the class?","Warning!",MB_YESNO|MB_ICONQUESTION) == IDYES)
    	{

    		CString className = m_classTree.GetItemText(m_classTree.GetSelectedItem());

    		int pos = className.Find(":");

    		if (pos!=-1){
    			className = className.Mid(pos+2);

    			pos = className.Find("<");

    			if (pos!=-1)
    				className = className.Left(pos-1);

    			if (classFactory.deleteClass(className))
    			{
    				DrawClasses(classFactory.getClassDef()->RootElement());
    			}

    		}
    	}

    }

    void CXmlclassDlg::OnDeleteAttribute()
    {
    	if ( MessageBox("Deleting an attribute donsen't afect to the instance objects that allready used it.\n\nDo you really want to delete the attribute?","Warning!",MB_YESNO|MB_ICONQUESTION) == IDYES)
    	{
    		CString className = m_classTree.GetItemText(m_classTree.GetParentItem(m_classTree.GetSelectedItem()));

    		int pos = className.Find(":");

    		if (pos!=-1){
    			className = className.Mid(pos+2);

    			pos = className.Find("<");

    			if (pos!=-1)
    				className = className.Left(pos-1);

    		CString attributeName = m_classTree.GetItemText(m_classTree.GetSelectedItem());
    		pos = attributeName.Find(":");

    		if (pos!=-1){
    			attributeName = attributeName.Mid(pos+2);

    				if (classFactory.deleteAttribute(className,attributeName))
    				{
    					DrawClasses(classFactory.getClassDef()->RootElement());
    				}

    			}

    		}
    	}

    }

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/xmlclassDlg.h] - (2,675 bytes)

    // xmlclassDlg.h : header file
    //

    #if !defined(AFX_XMLCLASSDLG_H__80332494_DEEC_43F3_B230_583E3254BCDE__INCLUDED_)
    #define AFX_XMLCLASSDLG_H__80332494_DEEC_43F3_B230_583E3254BCDE__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #include "ClassFactory.h"
    #include "NewInstanceDlg.h"
    #include "NewClassDlg.h"
    #include "NewAttributeDlg.h"

    /////////////////////////////////////////////////////////////////////////////
    // CXmlclassDlg dialog

    class CXmlclassDlg : public CDialog
    {
    // Construction
    public:
    	void SetObjectInstaceData(CString data);
    	void DrawContext(TiXmlElement* context);
    	void resetUI();
    	void DrawClasses(TiXmlElement* classes);
    	void initControls();
    	CXmlclassDlg(CWnd* pParent = NULL);	// standard constructor

    // Dialog Data
    	//{{AFX_DATA(CXmlclassDlg)
    	enum { IDD = IDD_XMLCLASS_DIALOG };
    	CButton	m_bDeleteAttribute;
    	CButton	m_bDeleteClass;
    	CButton	m_bNewAttribute;
    	CButton	m_bDeleteInstance;
    	CTreeCtrl	m_contextTree;
    	CButton	m_bNewInstance;
    	CTreeCtrl	m_classTree;
    	CString	m_instanceName;
    	CString	m_attributeName;
    	CString	m_value;
    	//}}AFX_DATA

    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CXmlclassDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
    	//}}AFX_VIRTUAL

    // Implementation
    protected:
    	HICON m_hIcon;

    	// Generated message map functions
    	//{{AFX_MSG(CXmlclassDlg)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	afx_msg void OnQuit();
    	afx_msg void OnLoadClasses();
    	afx_msg void OnSelchangedClassesTree(NMHDR* pNMHDR, LRESULT* pResult);
    	afx_msg void OnNewInstance();
    	afx_msg void OnSelchangedContextTree(NMHDR* pNMHDR, LRESULT* pResult);
    	afx_msg void OnDeleteInstance();
    	afx_msg void OnSetValue();
    	afx_msg void OnGetValue();
    	afx_msg void OnDblclkContextTree(NMHDR* pNMHDR, LRESULT* pResult);
    	afx_msg void OnSaveClasses();
    	afx_msg void OnLoadContext();
    	afx_msg void OnSaveContext();
    	afx_msg void OnNewClass();
    	afx_msg void OnNewAttribute();
    	afx_msg void OnDeleteClass();
    	afx_msg void OnDeleteAttribute();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()

    	CImageList m_classDefImages;
    	CImageList m_contextImages;

    	CClassFactory classFactory;

    	CNewInstanceDlg newInstanceDlg;
    	CNewClassDlg newClassDlg;
    	CNewAttributeDlg newAttributeDlg;
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_XMLCLASSDLG_H__80332494_DEEC_43F3_B230_583E3254BCDE__INCLUDED_)

Currently browsing [xmlclass.zip] (149,064 bytes) - [xmlclass/ClassFactory.cpp] - (11,641 bytes)

    #include "stdafx.h"

    #include "ClassFactory.h"

    CClassFactory::CClassFactory()
    {

    }

    CClassFactory::~CClassFactory()
    {
    	//don't forget to clear the documents. Just in case
    	clearClasDef();
    	clearCurContext();
    }

    void CClassFactory::clearClasDef()
    {
    	//just clear the document
    	classesDefinitions.Clear();

    }

    void CClassFactory::clearCurContext()
    {
    	//just clear the document
    	currentContext.Clear();
    }

    bool CClassFactory::loadContext(const char *filename)
    {
    	//We load the file, and check Error
    	if (! currentContext.LoadFile(filename))
    	{
    		error("Error loading file = \"%s\" : %s.", filename,
    			currentContext.ErrorDesc());
    		return false;
    	}
    	else
    		return true;

    }

    bool CClassFactory::saveContext(const char *filename)
    {
    	//We save the file, and check Error
    	if (! currentContext.SaveFile(filename))
    	{
    		error("Error saving file = \"%s\" : %s.", filename,
    			currentContext.ErrorDesc());
    		return false;
    	}
    	else
    		return true;
    }

    bool CClassFactory::loadClassDef(const char *filename)
    {
    	//We load the file, and check Error
    	if (! classesDefinitions.LoadFile(filename))
    	{
    		error("Error loading file = \"%s\" : %s.", filename,
    			classesDefinitions.ErrorDesc());
    		return false;
    	}
    	else
    		return true;
    }

    bool CClassFactory::saveClassDef(const char *filename)
    {
    	//We save the file, and check Error
    	if (! classesDefinitions.SaveFile(filename))
    	{
    		error("Error saving file = \"%s\" : %s.", filename,
    			classesDefinitions.ErrorDesc());
    		return false;
    	}
    	else
    		return true;
    }

    bool CClassFactory::newInstance(const char * className,
    								const char* instanceName)
    {
    	TiXmlNode* classNode = findClass(className);

    	//we din't find the class
    	if (classNode == NULL)
    	{
    		error("Couldn't find class %s",className);
    		return false;
    	}
    	else
    	{
    		TiXmlElement* root = currentContext.RootElement();

    		//if document it's empty
    		if (root == NULL)
    		{
    			//create a root node
    			currentContext.Parse ("<instances/>");
    			root = currentContext.RootElement();
    		}

    		//new node for the instance
    		TiXmlElement element("instance");

    		//add the attributes to the instace
    		if (addAttributesToInstance(&element, classNode))
    		{
    			element.SetAttribute("class", className);
    			element.SetAttribute("name", instanceName);

    			//we add the instance it self
    			root->InsertEndChild(element);
    		}
    		else
    			return false;
    	}

    	return true;
    }

    TiXmlNode* CClassFactory::findClass(const char *className)
    {
    	TiXmlNode* classNode = NULL;
    	bool found = false;

    	TiXmlElement* root = classesDefinitions.RootElement();

    	//if the document is empty return NULL
    	if (root == NULL)
    	{
    		return NULL;
    	}

    	//first class def
    	classNode = root->FirstChild("class");
    	const char* classNodeName;

    	//until be found it or they are no more class def
    	while ((classNode != NULL) && (!found))
    	{
    		//get the name of the class
    		classNodeName = classNode->ToElement()->Attribute("name");

    		//is the one?
    		if (strcmpi(classNodeName , className) == 0)
    			found = true;
    		else
    			//go to the next
    			classNode = classNode->NextSibling("class");
    	}

    	return ((found)?classNode:NULL);
    }

    bool CClassFactory::deleteInstace(const char *instanceName)
    {
    	TiXmlNode* instanceNode = findInstance(instanceName);

    	//if we donde find it the instance
    	if (instanceNode == NULL)
    	{
    		error("Couldn't find instance %s",instanceName);
    		return false;
    	}
    	else
    		//remove the instance node
    		currentContext.RootElement()->RemoveChild(instanceNode);

    	return true;
    }

    TiXmlNode* CClassFactory::findInstance(const char *instanceName)
    {
    	TiXmlNode* instanceNode = NULL;
    	bool found = false;

    	TiXmlElement* root = currentContext.RootElement();

    	//if the document is empty we return NULL
    	if (root == NULL)
    	{
    		return NULL;
    	}

    	//get first instance node
    	instanceNode = root->FirstChild("instance");
    	const char* instanceNodeName;

    	//until we found it or they are not more nodes
    	while ((instanceNode != NULL) && (!found))
    	{
    		//get instance name
    		instanceNodeName = instanceNode->ToElement()->Attribute("name");

    		//check if its the one
    		if (strcmpi(instanceNodeName , instanceName) == 0)
    			found = true;
    		else
    			//go to the next
    			instanceNode = instanceNode->NextSibling("instance");
    	}

    	return (found)?instanceNode:NULL;
    }

    bool CClassFactory::setValue(const char *instanceName,
    							 const char *attributeName, const char *value)
    {
    	TiXmlNode* instanceNode = findInstance(instanceName);

    	//if we don't find the instance
    	if (instanceNode == NULL)
    	{
    		error("Couldn't find instance %s",instanceName);
    		return false;
    	}
    	else
    	{
    		TiXmlNode* attributeNode  = instanceNode->FirstChild(attributeName);

    		//if we don't find the attribute
    		if (attributeNode == NULL)
    		{
    			error("Couldn't find attribute %s",attributeName);
    			return false;
    		}
    		else
    		{
    			//if the attribute have a value (values are childs from attribute)
    			if (attributeNode->FirstChild() != NULL)
    				//set the value
    				attributeNode->FirstChild()->SetValue(value);
    			else
    			{
    				//add the value as children
    				TiXmlText text(value);
    				attributeNode->InsertEndChild(text);
    			}
    		}
    	}
    	return true;
    }

    CString CClassFactory::getValue(const char *instanceName,
    								const char *attributeName)
    {
    	//by default "" value
    	CString value;
    	value = "";

    	TiXmlNode* instanceNode = findInstance(instanceName);

    	//if we din't found the instance
    	if (instanceNode == NULL)
    		error("Couldn't find instance %s",instanceName);
    	else
    	{
    		TiXmlNode* attributeNode  = instanceNode->FirstChild(attributeName);

    		//if we find the attribute
    		if (attributeNode == NULL)
    			error("Couldn't find attribute %s",attributeName);
    		else
    			//if is have a value (values are childs from attribute)
    			if (attributeNode->FirstChild() != NULL)
    				value = attributeNode->FirstChild()->Value();
    	}
    	return value;
    }

    bool CClassFactory::addAttributesToInstance(TiXmlElement *element,
    											TiXmlNode *classNode)
    {
    	TiXmlNode* attributeNode;
    	const char* attributeName;

    	//we get the first attribute
    	attributeNode = classNode->FirstChild("attribute");

    	//until we have not more attributes
    	while (attributeNode != NULL)
    	{
    		//get the name
    		attributeName = attributeNode->ToElement()->Attribute("name");

    		//add the attribute to the instance
    		TiXmlElement attrInstance (attributeName);
    		element->InsertEndChild(attrInstance);

    		//next attribute node
    		attributeNode = attributeNode->NextSibling("attribute");
    	}

    	const char* extends = NULL;

    	extends = classNode->ToElement()->Attribute("extends");

    	//if this class have a parent class
    	if (extends != NULL)
    	{
    		TiXmlNode* parentClassNode = findClass(extends);

    		//the parent class dosen't exist
    		if (parentClassNode == NULL)
    		{
    			error("Error couldn't find parent class %s",extends);
    			return false;
    		}
    		else
    			//add the attribute of the parent class (recursive)
    			return addAttributesToInstance(element, parentClassNode);
    	}

    	return true;
    }

    bool CClassFactory::addClass(const char *className, const char *extends)
    {
    	TiXmlNode* classNode = findClass(className);

    	//if we allready have that class
    	if (classNode != NULL)
    	{
    		error("Class allready exits %s",className);
    		return false;
    	}
    	else
    	{
    		//new class def node
    		TiXmlElement element("class");

    		element.SetAttribute("name", className);

    		//if we set a parent class
    		if (extends != NULL)
    		{
    			//if we set a not empty class name
    			if (strcmpi(extends,"") != 0)
    			{
    				classNode = findClass(extends);
    				//if we din't find the parent class
    				if (classNode == NULL)
    				{
    					error("Parent class dont found %s","extends");
    					return false;
    				}
    				else
    					//set the parent as attribute of the node
    					element.SetAttribute("extends", extends);
    			}
    		}

    		TiXmlElement* root = classesDefinitions.RootElement();

    		//if document its empty
    		if (root == NULL)
    		{
    			//add a root node
    			classesDefinitions.Parse("<classes/>");
    			root = classesDefinitions.RootElement();
    		}

    		//insert the class def
    		root->InsertEndChild(element);
    	}

    	return true;;
    }

    bool CClassFactory::addAttribute(const char *className,
    								 const char *attributeName)
    {
    	TiXmlNode* classNode = findClass(className);

    	//if we din't find the class
    	if (classNode == NULL)
    	{
    		error("Class dosen't exits %s",className);
    		return false;
    	}
    	else
    	{
    		const char* findAttributeName = NULL;

    		bool found = false;

    		//get the fist attribute node
    		TiXmlNode* attributeNode = classNode->FirstChild("attribute");

    		//until be found it or they aren't more attributes nodes
    		while ((attributeNode != NULL) && (!found))
    		{
    			//get the attribute name
    			findAttributeName = attributeNode->ToElement()->Attribute("name");

    			//check if its the one
    			if (strcmpi(findAttributeName , attributeName) == 0)
    				found = true;
    			else
    				//go to the next attribute
    				attributeNode = attributeNode->NextSibling("attribute");
    		}

    		//if we found it
    		if (found)
    		{
    			error("Attribute allready defined for the class %s",attributeName);
    			return false;
    		}
    		else
    		{
    			//add the attribute to the class
    			TiXmlElement element("attribute");

    			element.SetAttribute("name", attributeName);

    			classNode->ToElement()->InsertEndChild(element);
    		}
    	}

    	return true;
    }

    bool CClassFactory::deleteClass(const char *className)
    {
    	TiXmlNode* classNode = findClass(className);

    	//if we din't find the class
    	if (classNode == NULL)
    	{
    		error("Cant find the class %s",className);
    		return false;
    	}
    	else
    		//we remove the class def node. this olso remove all childrens
    		classesDefinitions.RootElement()->RemoveChild(classNode);

    	return true;
    }

    bool CClassFactory::deleteAttribute(const char *className,
    									const char *attributeName)
    {
    	TiXmlNode* classNode = findClass(className);

    	//if we din't find the class name
    	if (classNode == NULL)
    	{
    		error("Class dosen't exits %s", className);
    		return false;
    	}
    	else
    	{
    		const char* findAttributeName = NULL;

    		bool found = false;

    		//get the first attribute node
    		TiXmlNode* attributeNode = classNode->FirstChild("attribute");

    		//until we found it or they aren't more attributes nodes
    		while ((attributeNode != NULL) && (!found))
    		{
    			//get the name
    			findAttributeName = attributeNode->ToElement()->Attribute("name");

    			//check if its the one
    			if (strcmpi(findAttributeName , attributeName) == 0)
    				found = true;
    			else
    				//go to the next
    				attributeNode = attributeNode->NextSibling("attribute");
    		}
    		//if we dont found it
    		if (!found)
    		{
    			error("Attribute dosen't exits for this class %s",attributeName);
    			return false;
    		}
    		else
    			//remove the attribute
    			classNode->RemoveChild(attributeNode);
    	}

    	return true;
    }

    void CClassFactory::error(char message[], ...)
    {
    	//nasty code to display error messages

    	static char messageBuffer[8192];

    	va_list argumentsPointer;

    	va_start(argumentsPointer, message);
    	vsprintf(messageBuffer, message, argumentsPointer);
    	va_end(argumentsPointer);

    	MessageBox(NULL,messageBuffer,"Error", MB_OK | MB_ICONEXCLAMATION);
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.