Click here to Skip to main content
15,867,305 members
Articles / Programming Languages / Objective C

XML Class Used to Store or Load Information

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
11 Feb 20033 min read 183.2K   2.7K   33   26
Serialize information stored as XML

Introduction

This article describes a class used for reading and writing information stored as XML. The main task is to manage information, not to validate. There is no need for other components for using this class. It is very fast and this is also the main purpose for it, to read or write XML as fast as possible.

The XMLDOM component is harder to use and much slower. Sometimes, you do not need to validate XML and the XML file is just plain XML and no formatting is done. Then, I think you will like it.

In the downloadable file, there is one help file (CHM) that describes methods. This file was done using doxygen. There are also small samples in the help file on how to use it.

The XML class is template based. Two methods need to be supported by the class that is wrapped, one for reading and one for writing. It is also possible to derive from the class and create your own reading or writing methods.

If you are reading UTF-8 formatted text, then you need to translate it first before sending it to the XML class. Unicode or ASCII is OK but other formats need to be converted before processing. If the class should have managed UTF-8 conversion or other types of features that isn’t really needed for streaming information to or from XML file, then this would have had impact on the speed.

It also uses buffered reading or writing. Blocks of information are completed in sections. I will try to update the code here with new features or add other types of code. But if you need the latest, then visit Gorep Development.

Note: The code included with this article is designed for effective use and not just meant for the tutorial.

Background

I created this class after having used XMLDOM. XML is a very helpful format when information should be stored. But if there is one "elephant" control like XMLDOM that is needed every time XML should be processed, then this might be a little too much. Now it is a very simple task to use XML and the price is very small (tiny overhead).

Using the Code

The class is really simple to use but the internals are advanced. It uses some general collection classes that are included. Also the CString class. Don’t know why the MFC team didn’t build the CString as one standalone class??? As time goes, you will get a little tired including MFC, only because you need CString. I use WTL and ATL mostly, so the solution was to create my own CString. Also, I like to do portable code ;-).

If you have any wishes about new or improved functionality, then don't hesitate to ask for it. I will try to add it (if it doesn’t interfere with speed).

Here is some sample code from the download demo:

C++
// class used for reading and writing
class CXMLBuffer
{
public:
   CXMLBuffer() : m_uIndex(0) { }
   CXMLBuffer( CString string ) : m_stringXML( string ), m_uIndex(0) { }
   
   CString GetXML() {
      return m_stringXML; }

   void Write( const TCHAR* pszBuffer, UINT uCount, UINT* puCount )
   {
      m_uIndex += uCount;
      TCHAR* psz = m_stringXML.GetBuffer( m_uIndex + 1 );
      psz = &psz[m_uIndex - uCount];
      memcpy( psz, pszBuffer, uCount );
      psz[uCount] = '\0';
      m_stringXML.ReleaseBuffer();
   }

   UINT Read( TCHAR* pszBuffer, UINT uCount, UINT* puCount )
   {
      TCHAR* psz = m_stringXML.GetBuffer( 0 );
      if( uCount + m_uIndex > m_stringXML.GetLength() )
      {
         uCount = m_stringXML.GetLength() - m_uIndex;
      }
      memcpy( pszBuffer, &psz[m_uIndex], uCount );
      m_uIndex += uCount;
      if( puCount != NULL )
      {
         *puCount = uCount;
      }
      return uCount;
   }

   unsigned m_uIndex;
   CString m_stringXML;
};

using namespace gd_xml_stream;

/**
 * SAMPLE 1
 * Extract words from text and insert them to XML buffer
 */
void Cxml1Doc::OnSampleSurroundwords()
{
   CString string, stringWord;
   reinterpret_cast<CEditView*>
     (m_viewList.GetHead())->GetWindowText( string );

   if( string.IsEmpty() )
   {
      ::AfxMessageBox( _T("No text to surround, type som words"), MB_OK );
      return;
   } // if( string.IsEmpty() ){

   const TCHAR* pszPosition = string;
   CXMLBuffer Buffer;
   CXMLArchive<CXMLBuffer> ar( &Buffer, 
         CXMLArchive<CXMLBuffer>::eWrite );

   ar << Child << _T("DOCUMENT");
   while( *pszPosition )
   {
      if( *pszPosition <= ' ' )
      {
         if( stringWord.IsEmpty() == false )
         {
            ar << Child << _T("WORD") << 
                 attribute( _T("LENGTH"), stringWord.GetLength() ) 
                 << (const TCHAR*)stringWord << EndNode;
         }

         while( *pszPosition && *pszPosition <= ' ' ) pszPosition++;
         stringWord.Empty();
         continue;
      }

      stringWord += *pszPosition;
      pszPosition++;
   } // while( *pszPosition ){

   if( stringWord.IsEmpty() == false )
   {
      ar << Child << _T("WORD") << attribute( _T("LENGTH"), 
          stringWord.GetLength() ) 
          << (const TCHAR*)stringWord << EndNode;
   }

   ar << End;
   ar.Flush();

   reinterpret_cast<CEditView*>
     (m_viewList.GetHead())->SetWindowText( Buffer.GetXML() );
}

/**
 * SAMPLE 2
 * Add values to XML object
 */
void Cxml1Doc::OnSampleHardcoded1()
{
   CXMLBuffer Buffer;
   CXMLArchive<CXMLBuffer> ar( &Buffer, 
       CXMLArchive<CXMLBuffer>::eWrite );

   ar << Child << _T("DOCUMENT")
         << Child << _T("CHILD") 
         << attribute( _T("A1"), 1 ) 
         << attribute( _T("A2"), 1.1 ) 
         << attribute( _T("A3"), _T("TEXT") ) 
         << _T("Value") << EndNode
         << Child << _T("CHILD") 
         << attribute( _T("A1"), 1 ) 
         << attribute( _T("A2"), 1.2 ) 
         << attribute( _T("A3"), _T("TEXT") ) 
         << _T("Value")
         << Child << _T("CHILD") 
         << attribute( _T("A1"), 1 ) 
         << attribute( _T("A2"), 1.3 ) 
         << attribute( _T("A3"), _T("TEXT") ) 
         << _T("Value") << EndNode << EndNode;
   ar << End;
   reinterpret_cast<CEditView*>
      (m_viewList.GetHead())->SetWindowText( Buffer.GetXML() );
}

/**
 * SAMPLE 3
 * Show how it is possible to read from XML formatted text.
 */
void Cxml1Doc::OnSampleReadtext()
{
   TCHAR* pszText =
      _T("<DOCUMENT>")
         _T("<ITEM A1=\"Attribute value\">Item value</ITEM>")
         _T("<ITEM A1=\"Attribute value\">Item value</ITEM>")
         _T("<ITEM A1=\"Attribute value\">")
            _T("<CHILDITEM A1=\"Attribute value\">xxxxxxxx</CHILDITEM>")
         _T("</ITEM>")
      _T("</DOCUMENT>");
   CString stringReport;
   CXMLBuffer Buffer( pszText );
   CXMLArchive<CXMLBuffer> ar( &Buffer );

   while( ar.ReadNext() == true )
   {
      if( ar.IsEndTag() == false )
      {
         CString stringName = (const TCHAR*)ar.GetName();

         stringReport += stringName;

         stringReport += _T("\r\n");

         if( stringName == _T("ITEM") )
         {
            ar.PreReadNext();
            CString stringNextName = (const TCHAR*)ar.GetNextName();
            if( stringNextName == _T("CHILDITEM") )
            {
               stringReport += _T("Next item is named CHILDITEM.");
               if( ar.HasNextChildren() == false )
               {
                  stringReport += 
                    _T(" And that item don't have any childrens");
               }
               stringReport += _T("\r\n");
            }
         }
      }
   }
   reinterpret_cast<CEditView*>
     (m_viewList.GetHead())->SetWindowText( stringReport );
}

History

Thanks to Stephan Rodriguez who pointed out compliance problem with VC 6.0. With help from him, it now should work with VC 6.0 (I don’t have VC 6.0 myself).

Added sample for saving file and class for converting to UTF8.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralGreat Work! Pin
Theo00714-Mar-04 3:16
Theo00714-Mar-04 3:16 
Generaltrust me... Pin
berndg12-Feb-03 9:45
berndg12-Feb-03 9:45 
GeneralRe: trust me... - Nope. Pin
Neville Franks12-Feb-03 10:10
Neville Franks12-Feb-03 10:10 
GeneralRe: trust me... - Nope. Pin
Zac Howland12-Feb-03 11:43
Zac Howland12-Feb-03 11:43 
GeneralRe: trust me... - Nope. Pin
Neville Franks12-Feb-03 12:41
Neville Franks12-Feb-03 12:41 
GeneralRe: trust me... - Nope. Pin
Zac Howland12-Feb-03 14:26
Zac Howland12-Feb-03 14:26 
GeneralRe: trust me... - Nope. Pin
Neville Franks12-Feb-03 15:51
Neville Franks12-Feb-03 15:51 
GeneralRe: trust me... - Nope. Pin
Anonymous18-Jul-03 21:19
Anonymous18-Jul-03 21:19 
GeneralRe: trust me... Pin
Nemanja Trifunovic12-Feb-03 10:33
Nemanja Trifunovic12-Feb-03 10:33 
GeneralRe: trust me... Pin
berndg12-Feb-03 20:01
berndg12-Feb-03 20:01 
GeneralRe: trust me... (I don't agree) Pin
gosh12-Feb-03 23:49
gosh12-Feb-03 23:49 
GeneralRe: trust me... (I don't agree) Pin
berndg13-Feb-03 0:12
berndg13-Feb-03 0:12 
GeneralRe: trust me... (I don't agree) Pin
scottblum17-Feb-03 12:49
sussscottblum17-Feb-03 12:49 
GeneralString Pin
Xalon12-Feb-03 5:34
Xalon12-Feb-03 5:34 
GeneralRe: String Pin
gosh12-Feb-03 5:48
gosh12-Feb-03 5:48 
GeneralRe: String Pin
Xalon12-Feb-03 6:58
Xalon12-Feb-03 6:58 
GeneralRe: String Pin
gosh12-Feb-03 8:18
gosh12-Feb-03 8:18 
GeneralRe: String Pin
gosh12-Feb-03 21:41
gosh12-Feb-03 21:41 
This morning I checked the std::string to see how optimized it is. I thought that they hade done some justifications for it and didn’t follow object oriented rules strictly to gain speed. What I saw was that they haven’t done much to make this class work faster. CString in MFC is much faster that std::string for example. The gd::CString is similar to MFC CString with some additional features to improve speed even more.
If someone should test performance for std::string compared to one string object that is optimized they will for sure find big speed improvements selecting one string object that is optimized.

Generaldocumentation Pin
scottblum10-Feb-03 11:00
sussscottblum10-Feb-03 11:00 
GeneralRe: documentation Pin
gosh11-Feb-03 6:20
gosh11-Feb-03 6:20 
GeneralRe: documentation Pin
Anonymous11-Feb-03 12:34
Anonymous11-Feb-03 12:34 
GeneralVC6 audience Pin
26-Oct-02 8:05
suss26-Oct-02 8:05 
GeneralRe: VC6 audience Pin
gosh26-Oct-02 9:46
gosh26-Oct-02 9:46 
GeneralRe: VC6 audience Pin
Chris Maunder26-Oct-02 9:54
cofounderChris Maunder26-Oct-02 9:54 
GeneralRe: VC6 audience Pin
gosh26-Oct-02 10:08
gosh26-Oct-02 10:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.