Skip to main content
Email Password   helpLost your password?

Introduction

Ever wonder what those Microsoft MFC message mapping macros did under the covers? It was always black magic to me - how clicking a button caused a function to be called. Luckily for the curious, Visual Studio lets you sleuth through the macros by using "Go to Definition" from the context menu.

I recently had a need to convert a structure to XML and vice versa in order to allow a web server to send TCP/IP messages to my server process - the messages would be formatted in XML, but the server would of course need to have access to the parsed XML elements in some sort of structure. There are a lot of XML parsers out there, including ActiveX controls - and so I make a disclaimer here that this is not intended to be a full featured parser. Our XML needs were very simple, and this is a simple solution.

But the purpose of the article is not really about XML parsing - it is about mapping the members of a class - either data or function - to a list, which contains information about the members, and associations to some function, so you can do something useful with the class members without having to write a bunch of code for each of your derived classes.

To better illustrate the point, take a look at the Microsoft message mapping macros (afxwin.h). There are four basic macro functions at work here.

We will use the following code as an example:

BEGIN_MESSAGE_MAP( CMyClass, CFrameWnd )
   ON_MESSAGE(CM_SOCKET_EVENT, OnSocketEvent)
   ON_MESSAGE(CM_FOLDER_CHANGED, OnFolderChanged )
END_MESSAGE_MAP()

That's basically all there is. In our XML mapping example, we use the mapping macros to create structures that describe the member variables. This initial version supports the following basic types, but can easily be extended for support of other atomic data types like float, etc.

Integers

Strings (CStrings, but could be ported to use any string type)

Classes - Must be derived from the CXMLMessage class

New Features for Version 1.01 (November 16, 2004)

New Features for Version 1.2 (November 18, 2004)

Background

Familiarity with Windows message handling, using the Windows macros described above.

Using the code

The XML mapping macros in this example are very easy to use. Exporting a class to XML is done using the Deflate() function, and Importing from XML is done using the Inflate() function.

Here is an example of the XML map, which is in the CPP file for the derived class.

Note: The syntax for Inflate and Deflate has changed for V1.01 - much simpler to use.

BEGIN_XML_MAP( CMsgDestinationInfo, _T("destinationInfo") )
   // OR with XML_POINTER, XML_ARRAY as necessary

   XML_ELEMENT_DTYPE( _T("destination"),  m_destination,  XML_STRING )
   XML_ELEMENT_DTYPE( _T("filePathRoot"), m_filePathRoot, XML_STRING )
END_XML_MAP()

Version 1.2 now supports derived classes. Use the BEGIN_XMP_MAP2 macro for these. You can derive as many levels as you need to. Each derived class will include the XML mapped members from its base class. In this example, CMsgFTPDestinationInfo will have the members "destination" and "filePathRoot" included from CMsgDestinationInfo.

BEGIN_XML_MAP2( CMsgFTPDestinationInfo, _T("ftpDestinationInfo"), 
                                           CMsgDestinationInfo )
   XML_ELEMENT_DTYPE( _T("username"),  m_username,  XML_STRING )  
   XML_ELEMENT_DTYPE( _T("password"),  m_password,  XML_STRING )
END_XML_MAP()

And the header file for our class - with map declaration. Note: constructors and destructors are automatically provided by the macros. If you need special behavior here, override Initialize() or Cleanup() in your derived class.

class CMsgDestinationInfo : public CXMLMessage
{
   public:
  
   CString m_destination;
   CString m_filePathRoot;

   DECLARE_XML_MAP(CMsgDestinationInfo);
};

Or in the case of a derived class:

class CMsgFTPDestinationInfo : public CMsgDestinationInfo 
{
   public:
  
   CString m_destination;
   CString m_filePathRoot;

   DECLARE_XML_MAP(CMsgFTPDestinationInfo );
};

I'll spare you the initialization of the class members, but assuming that is done, here is how you generate the XML:

// Our XML Message object

CMsgFTPDestinationInfo message1;

int size = 0;
TCHAR* ptr = 0;

// Deflate the object ( save as XML )

if ( message1.Deflate( ptr, size ) != 0 )
   return 1; // Failed if ( message1.Deflate( ptr, size ) != 0 )


// ptr & size are now valid. ptr is deleted when message1 destructs.

And here is how you load the class members from an XML buffer (read from a file, socket, etc.):

// Inflate a new object from the XML buffer

CMsgFTPDestinationInfo message2;
if ( message2.Inflate( ptr, size ) != 0 )
    return 1; // Failed

Generating schema definition files is easy:

CMsgFTPDestinationInfo message3;
if ( message3.GenerateDTD() != 0 ) // Document Type Definitions

    return 1; 
if ( message3.GenerateXSD() != 0 ) // XML Schema Definitions

    return 1; // Failed

Points of Interest

I enjoy doing things you aren't supposed to be able to do - like manipulating and recasting pointers. Everything that is done in software is done by interpreting the meaning of a block of memory. And trying to understand how the compiler interprets pointers and what expects to find in a block of memory is always a fun challenge.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralReference to XML_ATTRIBUTE Pin
c-sharp
4:54 28 Apr '06  
GeneralRe: Reference to XML_ATTRIBUTE Pin
Steve Johnson (Sven)
5:14 28 Apr '06  
GeneralBug in CXMLMessage::DeflateInteger(...) ? Pin
OKN
1:02 4 Nov '05  
GeneralRe: Bug in CXMLMessage::DeflateInteger(...) ? Pin
Steve Johnson (Sven)
6:37 4 Nov '05  
GeneralGreat for serialization Pin
CasualT
13:33 30 May '05  
GeneralHow to use with Collections Pin
c-sharp
6:32 27 May '05  
GeneralRe: How to use with Collections Pin
Steve Johnson (Sven)
7:14 27 May '05  
GeneralRe: How to use with Collections Pin
Steve Johnson (Sven)
7:28 27 May '05  
GeneralRe: How to use with Collections Pin
Steve Johnson (Sven)
7:39 27 May '05  
GeneralImprovements for multiple inheritance Pin
KenGuru
0:03 18 Nov '04  
GeneralRe: Improvements for multiple inheritance Pin
Steve Johnson (Sven)
11:05 18 Nov '04  
GeneralThis is What I Want Pin
sudhir mangla
21:36 15 Nov '04  
GeneralNice, look what I did Pin
Anonymous
7:31 11 Nov '04  


Last Updated 21 Nov 2004 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009