Click here to Skip to main content
15,884,628 members
Articles / Desktop Programming / MFC
Article

RTSXML Parser

Rate me:
Please Sign up or sign in to vote.
2.67/5 (3 votes)
29 Feb 20042 min read 29.8K   358   17   2
Extension of Object Oriented XML Parser.

Introduction

I have a project to develop flexible menus and screens, and I am thinking to use XML as my format for the configuration file.

Thanks to Mike Melnikov. I read his project: "object-oriented XML parser" and I thought about how to adopt the project to mine.

Unfortunately, I have difficulty to adopt his project, because:

  • I couldn’t put his project to became one .dll library and used by another .dll library.
  • I can’t find a way to get data without ‘breaking’ the object-oriented structure.
  • I like to use classes not structures.

So, I tried to read how his project worked and reengineered his project to my XML project. I changed the name to become RTSXML.dll.

Requirement

  • I need accessing tree in a comfort way (well, at least for myself :-)).
  • I need accessing child node in an elegant way, with no ‘breaking’ the OO concept.

Solution

I am still using the parser from ‘Object-oriented XML parser’ project and developed my own tree class structured.

// read xml document and parse info CRTSXMLNode tree 
CRTSXMLNode *CRTSXMLManager::Read(LPCTSTR filename)
{
    CRTSXMLNode *pRoot = NULL; 
    if (SUCCEEDED(CreateDocument()))  // create document
    {
        if (SUCCEEDED(m_pIXMLDOMDocument->put_async(VARIANT_FALSE)))
        {
            // load and parse
            VARIANT_BOOL vSuccess = 
                m_pIXMLDOMDocument->load(_variant_t(filename)); 
            if(vSuccess)
            {
                MSXML::IXMLDOMNodePtr pNode  = m_pIXMLDOMDocument;
                if (pNode)
                {
                    pRoot = new CRTSXMLNode;
                    pRoot->m_sTitle = "Root RTSXMLDocument";
                    pRoot->m_nOrder = 1; 
                    // create a tree of xml document
                    CreateRTSXMLNode(pNode, pRoot);
                    m_pIXMLDOMDocument = NULL; 
                    return pRoot;   
                    // success
                }
            }
        }
    } 

    // error found
    ReportError(m_pIXMLDOMDocument->GetparseError());
    return NULL;
}

The concept of tree structure is like this: in every node of the tree there are some child nodes and some attribute values:

class CRTSXMLNode  

{
public:
     [..deleted…]
     CMapStringToString m_pAttrs;
     CArray<CRTSXMLNode *, CRTSXMLNode *> m_pChilds;
     [...deleted…] 
public:
     CRTSXMLNode();
     virtual ~CRTSXMLNode(); 
public:
     int GetFirstAttr(CString &key, CString &value);
     int GetNextAttr(CString &key, CString &value);
     int GetAttr(LPCTSTR key, int &value, int failedValue=-1);
     int GetAttr(LPCTSTR key, CString &value);
     int NumberOfAttrs() { return m_pAttrs.GetCount(); } 
public:
     CRTSXMLNode *GetFirstChild();
     CRTSXMLNode *GetNextChild();
     CRTSXMLNode *GetChilds(LPCTSTR key);
     CRTSXMLNode *GetChild(int nOrder);
     int NumberOfChilds() { return m_pChilds.GetUpperBound()+1; }
     CRTSXMLNode *FindChilds(LPCTSTR keyTitle); 
public:
     void AddAttr(LPCTSTR key, LPCTSTR value) { m_pAttrs.SetAt(key, value); }
     void AddChild(CRTSXMLNode *node); 

     void ReleaseAttrs();
     void ReleaseChilds(); 
public:
     void Trace(int nLevel=0); 
}

I am using CMapStringToString to keep my attribute values, because I need a fast access to the attribute without worrying about the order of attribute appearance and using CArray to keep child nodes based on order of appearance.

How to use

I am thinking “reusability” without changing anything in future projects, so I created RTSXML.dll library for those implementations.

For using the library, I created two new classes outside of the library: CXMLWindowReader and CXMLWindow.

CXMLWindowReader is a class for preparing and reading the XML file. Result of this class is CXMLNode and becomes input for CXMLWindow.

CXMLWindow is a generalization of lexical class. For this sample, I created CXMLMenu which inherited from CXMLWindow.

class EXT_WINDOW_CLASS CXMLMenu : public CXMLWindow  
{
protected:
     CMenu *m_pMenu;
     CMenu m_pBuffer[100];
     int m_nBuffer; 
protected:
     int CreateMenu(CMenu *pMenu, CRTSXMLNode *pNode); 
public:
     CXMLMenu(CMenu *pMenu = NULL);
     virtual ~CXMLMenu(); 

public:
     void SetMenu(CMenu *pMenu) { m_pMenu = pMenu; } 
public:
     int Build(CRTSXMLNode *pNode); 
};

and the important thing is implementation of int Build(CRTSXMLNode *pNode) function, which looks like this:

int CXMLMenu::Build(CRTSXMLNode *pNode)
{
     return CreateMenu(m_pMenu, pNode);
} 
int CXMLMenu::CreateMenu(CMenu *pMenu, CRTSXMLNode *pNode)
{
     CString szValue;
     CString szDesc;
     int nId; 
     CRTSXMLNode *child = pNode->GetFirstChild();
     while (child)
     {
          if (child->m_sTitle == "popup")
          {
               CMenu *pSubMenu = &m_pBuffer[m_nBuffer++]; 
               pSubMenu->CreatePopupMenu();
               child->GetAttr("menu", szValue);
               pMenu->AppendMenu(MF_POPUP, (UINT)pSubMenu->m_hMenu, szValue);
               CreateMenu(pSubMenu, child);
          }
          else
          if (child->m_sTitle == "item")
          {
               child->GetAttr("menu", szValue);
               child->GetAttr("text", szDesc);
               child->GetAttr("id", nId); 
               if (szValue == "separator")
                    pMenu->AppendMenu(MF_SEPARATOR, 0);
               else
               {
                    pMenu->AppendMenu(MF_STRING, nId, szValue);
               }
          }

          child = pNode->GetNextChild();
     }
     return 1;
}

In “menu” node (not shown in code above. See the source code) there are two kinds of child nodes: they are “popup” and “item”.

“popup” is used to define popup menu and “item” is used to define item of the menu. Every popup menu can have two child nodes: these are another popup menu and item.

For complete reference, you could download my source code. Thank you.

In my next article, I will explain how to implement frame window using XML configuration file.

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
Indonesia Indonesia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionhow to avoid memory leaks in MSXML Pin
girishnadig25-Feb-05 5:19
girishnadig25-Feb-05 5:19 
GeneralSuggestions Pin
Stephane Rodriguez.29-Feb-04 22:12
Stephane Rodriguez.29-Feb-04 22:12 

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.