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.