Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

How To Serialize a CTreeCtrl in XML

, 3 May 2006 CPOL
Extend derived CTreeCtrl classes with an easy and fast to use approach for XML serialisation.
#include "StdAfx.h"
#include "TreeCtrlXML.h"

#include <direct.h>		// Needed for getcwd()

CTreeCtrlXML::CTreeCtrlXML(void)
{
}

CTreeCtrlXML::~CTreeCtrlXML(void)
{
}

bool CTreeCtrlXML::LoadFromXML( const CString& a_strFile )
{
	TiXmlNode* pXML = NULL;
	TiXmlDocument xmlDoc;

	char szBuf[ _MAX_PATH + 1 ];
	CString strTemp = a_strFile;

	getcwd( szBuf, sizeof( szBuf ) );
	strcat( szBuf, "\\" );
	strcat( szBuf, strTemp.GetBuffer( 1 ) );

	if( xmlDoc.LoadFile( szBuf ) )
	{
		// XML root
		pXML = xmlDoc.FirstChild( "XML" );

		if( NULL == pXML )
			return false;

		// Load our tree control
		Load( pXML );

		// Expand all entries
		Expand( GetRootItem(), TVE_EXPAND );

		return true;
	}
    
	return false;
}

bool CTreeCtrlXML::SaveToXML( const CString& a_strFile )
{
	// Save XML
	TiXmlNode* pXML = NULL;
	TiXmlDocument xmlDoc;

	// XML header
	xmlDoc.InsertEndChild( TiXmlDeclaration( "1.0", "UTF-8", "yes" ) );

	// XML root
	pXML = xmlDoc.InsertEndChild( TiXmlElement( "XML" ) );

	// Save our tree control
	Save( pXML );

	// Save XML
	CString strFile = a_strFile;

	return xmlDoc.SaveFile( strFile.GetBuffer( 1 ) );
}

void CTreeCtrlXML::Load( TiXmlNode* a_pNode )
{
	ASSERT( NULL != a_pNode );

	// Get node "Items"
	TiXmlNode* pItems = a_pNode->FirstChild( "Items" );
	TiXmlNode* pItem = NULL;

	if( NULL == pItems )
		return;

	// Get first item
	pItem = pItems->FirstChild( "Item" );

	// Iterate all siblings
	while( NULL != pItem )
	{
		LoadItem( pItem, NULL );
		pItem = pItem->NextSibling( "Item" );
	}
}

void CTreeCtrlXML::Save( TiXmlNode* a_pNode )
{
	ASSERT( NULL != a_pNode );

	TiXmlNode* pItems = a_pNode->InsertEndChild( TiXmlElement( "Items" ) );
	TiXmlNode* pParent = pItems;
	TiXmlNode* pNewNode = NULL;
	HTREEITEM hItem = GetRootItem();
	int iIndent = 0; int iLastIndent = 0;

	while( hItem )
	{
		iIndent = GetIndentLevel( hItem );

		int iDiff = iIndent - iLastIndent;
		if( iDiff > 0 )
		{
			ASSERT( NULL != pNewNode );

			while( iDiff-- )
				pNewNode = pNewNode->InsertEndChild( TiXmlElement( "Item" ) );

			ASSERT( NULL != pNewNode );
			pParent = pNewNode->Parent();
		}
		else if( iDiff < 0 )
		{
			iDiff--;					// Correct difference to get the right parent
			pParent = pNewNode;

			while( iDiff++ < 0 )
				pParent = pParent->Parent();

			ASSERT( NULL != pParent );
			pNewNode = pParent->InsertEndChild( TiXmlElement( "Item" ) );
		}
		else 
		{
			ASSERT( NULL != pParent );
			pNewNode = pParent->InsertEndChild( TiXmlElement( "Item" ) );
		}

		iLastIndent = iIndent;			

		// Save current item
		TiXmlElement* pElement = pNewNode->ToElement();
		ASSERT( NULL != pElement );

		pElement->SetValue( "Item" );
		pElement->SetAttribute( "Title", GetItemText( hItem ) );

		// The next item, please ...
		hItem = GetNextItem( hItem );
	}
}

void CTreeCtrlXML::LoadItem( TiXmlNode* a_pNode, HTREEITEM a_hTreeParent )
{
	ASSERT( NULL != a_pNode );

	TiXmlElement* pEl = a_pNode->ToElement();
	ASSERT( NULL != pEl );

	HTREEITEM hItem = NULL;

	TiXmlNode* pChild = NULL;

	if( NULL == a_hTreeParent )
		hItem = InsertItem( pEl->Attribute( "Title" ), TVI_ROOT );
	else
		hItem = InsertItem( pEl->Attribute( "Title" ), a_hTreeParent );

	pChild = a_pNode->IterateChildren( "Item", NULL );

	while( pChild )
	{
		LoadItem( pChild, hItem );
		pChild = a_pNode->IterateChildren( "Item", pChild );
	}
}

int CTreeCtrlXML::GetIndentLevel( HTREEITEM hItem )
{
	int iIndent = 0;

	while( (hItem = GetParentItem( hItem )) != NULL )
		iIndent++;

	return iIndent;
}

HTREEITEM CTreeCtrlXML::GetNextItem( HTREEITEM hItem )
{
	HTREEITEM hItemRet = NULL;

	if( false == ItemHasChildren( hItem ) )
	{
		while( ( hItemRet = GetNextSiblingItem( hItem ) ) == NULL )
		{
			if( ( hItem = GetParentItem( hItem ) ) == NULL )
				return NULL;
		}
	}
	else
	{
		return GetChildItem( hItem );
	}

	return hItemRet;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Andreas Loeffler
Web Developer
Germany Germany
I was born in 1982 near Stuttgart / Germany and began my first steps in programming computers at the age of only nine years on an old Commodore CBM 7072. In 2002 I finished my education as IT specialist for software engineering and did my civillian service afterwards. Currently I'm working as leader of the software division in a bigger company located in south west Germany, mainly on software development and research projects for multimedia terminals and user recognition/verification systems.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 3 May 2006
Article Copyright 2006 by Andreas Loeffler
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid