Click here to Skip to main content
Licence GPL3
First Posted 31 Mar 2008
Views 10,516
Downloads 54
Bookmarked 7 times

Fast Xml Utility

By | 31 Mar 2008 | Article
A fast utility to deal with xml

Introduction

A fast utility to deal with xml.

Background

When you want to create such a xml file to describe you struct:

<?xml version="1.0" encoding="UTF-8" ?>
- <Body>
- <Item>
< <szContactListName>item1</szContactListName>
<szContactListPath>D:\asdsad.txt</szContactListPath>
<dwContactNum>2</dwContactNum>
<CreateTime>1206964933</CreateTime>
</Item>
<Item>
< <szContactListName>item2</szContactListName>
<szContactListPath>D:\22.txt</szContactListPath>
<dwContactNum>6</dwContactNum>
<CreateTime>1206963246</CreateTime>
</Item>
... ...
</Body>
and when you need to create 10+ this xmls, did you think to do something
to reduce the work?
CXMLFileCommon is designed for this.

Using the code

Code of CXMLFileCommon.h

/*




XML File Common
XMLFileCommon.h
*/



#ifndef __XMLFILECOMMON_H__
#define __XMLFILECOMMON_H__
#include "list"
using namespace std;
#include "assert.h"
#include "atlbase.h"
#include "atlconv.h"
#include "msxml.h"
#pragma  comment(lib, "msxml2.lib")
#pragma warning(disable : 4786)
template <class T, class P>
class __declspec(novtable) CXMLFileCommon
{
public:
 enum XMLOPERATION
 {
  xml_add = 0,
  xml_modify,
  xml_del,
  xml_getall,
  xml_getfirstmatch
 };
protected:
 struct XMLNODEINFO
 {
  TCHAR* szNode;
  TCHAR* szValueType;
  int  nOffset;
 };
#define BEGIN_XML_MAP() \
 static const XMLNODEINFO* _XMLMap() \
 { \
 static const XMLNODEINFO _XmlNodeMap[] = \
 { 
#define XML_MAP(Node, ValueType, s) \
 {_T(#Node), _T(#ValueType), offsetof(s, Node)}, \
#define END_XML_MAP() \
 {NULL, NULL, 0} \
 }; \
 \
 return &_XmlNodeMap[0];  \
 } 
 CString GetValue(CString szValueType, DWORD Address)
 {
  CString szValue;
  if ( szValueType == _T("CString") )
  {
   szValue = *(CString*)Address;
   return szValue;
  }
  if ( szValueType == _T("DWORD") )
  {
   szValue.Format(_T("%d"), *(DWORD*)Address);
   return szValue;
  }
  if ( szValueType == _T("BOOL") )
  {
   szValue.Format(_T("%d"), *(DWORD*)Address);
   return szValue;
  }
  if ( szValueType == _T("time_t") )
  {
   szValue.Format(_T("%ld"), *(time_t*)Address);
   return szValue;
  }
  if ( szValueType == _T("ULONG") )
  {
   szValue.Format(_T("%ld"), *(ULONG*)Address);
   return szValue;
  }
  if ( szValueType == _T("int") ) 
  {
   szValue.Format(_T("%d"), *(int*)Address);
   return szValue;
  }
  if ( szValueType == _T("UINT64") ) 
  {
   szValue.Format(_T("%ld"), *(UINT64*)Address);
   return szValue;
  }
  assert(0);
  // Struct item type UnSupport.
  return szValue;
 }
 BOOL SetValue(CString szValueType, DWORD Address, CString szValue)
 {
  USES_CONVERSION;
  if ( szValueType == _T("CString") )
  {
   *(CString*)Address = szValue;
   return TRUE;
  }
  if ( szValueType == _T("DWORD") )
  {
   *(DWORD*)Address = atol(T2A(szValue.GetString()));
   return TRUE;
  }
  if ( szValueType == _T("BOOL") )
  {
   *(BOOL*)Address = atol(T2A(szValue.GetString()));
   return TRUE;
  }
  if ( szValueType == _T("time_t") )
  {
   *(time_t*)Address = _atoi64(T2A(szValue.GetString()));
   return TRUE;
  }
  if ( szValueType == _T("ULONG") )
  {
   *(ULONG*)Address = atol(T2A(szValue.GetString()));
   return TRUE;
  }
  if ( szValueType == _T("int") )
  {
   *(int*)Address = atoi(T2A(szValue.GetString()));
   return TRUE;
  }
  if ( szValueType == _T("UINT64") ) 
  {
   *(UINT64*)Address = _atoi64(T2A(szValue.GetString()));
   return TRUE;
  }
  assert(0);
  // Struct item type UnSupport.
  return FALSE;
 }
 BOOL Get(CComPtr<IXMLDOMNode> pNode,  T& t)
 {
  USES_CONVERSION;
  // pNode is "Item"
  if ( pNode == NULL )
   return FALSE;
  const XMLNODEINFO* pMap = P::_XMLMap();
  for (int i = 0; pMap[i].szNode != _T('\0'); i++ )
  {
   CString szNode = pMap[i].szNode;
   CString szValueType = pMap[i].szValueType;
   CString szValue;
   CComPtr<IXMLDOMNode> __spNode = NULL;
   if ( FAILED(pNode->selectSingleNode(CComBSTR(szNode), &__spNode)) || __spNode == NULL )
    return FALSE;
   BSTR bstr;
   if ( __spNode )
   {
    __spNode->get_text(&bstr);
    szValue = OLE2T(bstr);
   }
   DWORD dwAddress = (DWORD)&t+(DWORD)pMap[i].nOffset;
   if ( IsBadReadPtr((void*)dwAddress, 1) )
    return FALSE;
   if ( !SetValue(szValueType, dwAddress, szValue) )
    return FALSE;
  }
  return TRUE;
 }
 BOOL Add(CComPtr<IXMLDOMNode> pNode,  T& t)
 { 
  // pNode is "Item"
  if ( pNode == NULL )
   return FALSE;
  const XMLNODEINFO* pMap = P::_XMLMap();
  for (int i = 0; pMap[i].szNode != _T('\0'); i++ )
  {
   CString szNode = pMap[i].szNode;
   CString szValueType = pMap[i].szValueType;
   CString szValue;
   DWORD dwAddress = (DWORD)&t+(DWORD)pMap[i].nOffset;
   if ( IsBadReadPtr((void*)dwAddress, 1) )
    return FALSE;
   szValue = GetValue(szValueType, dwAddress);
   CComPtr<IXMLDOMNode> pNodeSub = NULL;
   if ( FAILED(pNode->selectSingleNode(CComBSTR(szNode), &pNodeSub)) )
    return FALSE;
   if ( !pNodeSub )
   {
    CComPtr<IXMLDOMElement> _spNode;
    if ( FAILED(m_spxmlDoc->createElement(CComBSTR(szNode), &_spNode)) || _spNode == NULL )
     return FALSE;
    if ( FAILED(pNode->appendChild(_spNode, NULL)) )
     return FALSE;
    pNodeSub = _spNode;
   }
   if ( pNodeSub )
   {
    if ( FAILED(pNodeSub->put_text(CComBSTR(szValue)) ) )
     return FALSE;
   }
  }
  return Save();
 }
public:
 CXMLFileCommon() 
 {  
  m_spxmlDoc  = NULL;
  m_szItemTag = _T("Item");
  m_szBodyTag = _T("Body");
  m_szComment = _T("Author: wak 2008.03.25");
  m_szEncode = _T("UTF-8");
 }
 void SetParams(
  CString szComment = _T("Xml by wak."),
  CString szEncode  = _T("UTF-8"),
  CString szItemTag = _T("Item"),
  CString szBodyTag = _T("Body") )
 {
  m_szBodyTag = szBodyTag;
  m_szItemTag = szItemTag;
  m_szEncode = szEncode;
  m_szComment = szComment;
 }
 ~CXMLFileCommon() { Release(); }
 BOOL Load()
 {
  USES_CONVERSION;
  // 
  // Init IXMLDOMDocument
  //
  assert( m_spxmlDoc == NULL );
  if ( FAILED(m_spxmlDoc.CoCreateInstance(CLSID_DOMDocument)) || m_spxmlDoc == NULL )
   return FALSE;
  if ( FAILED(m_spxmlDoc->put_async(VARIANT_FALSE)) )
   return FALSE;
  VARIANT_BOOL vbool;
  COleVariant vVar(m_szXmlFile);
  if ( FAILED(m_spxmlDoc->load(vVar, &vbool)) || vbool == VARIANT_FALSE )
   return FALSE;
  return TRUE;
 }
 BOOL Release()
 {
  if ( m_spxmlDoc )
  {
   m_spxmlDoc.Release();
   m_spxmlDoc = NULL;
  }
  return TRUE;
 }
 void SetXmlName(CString szFileName)
 {
  m_szXmlFile = szFileName;
  assert(!m_szXmlFile.IsEmpty());
 }
 BOOL InitXML(BOOL bOverWrite = FALSE)
 {
  USES_CONVERSION;
  assert(!m_szXmlFile.IsEmpty());
  CComPtr<IXMLDOMDocument> spIXMLDoc;
  if ( FAILED(spIXMLDoc.CoCreateInstance(CLSID_DOMDocument)) || spIXMLDoc == NULL )
   return FALSE;
  if ( FAILED(spIXMLDoc->put_async(VARIANT_FALSE)) )
   return FALSE;
  if ( ::GetFileAttributes(m_szXmlFile) != -1 )
  {
   VARIANT_BOOL vbool;
   COleVariant vVar(m_szXmlFile);
   if ( SUCCEEDED(spIXMLDoc->load(vVar, &vbool)) && vbool == VARIANT_TRUE  && !bOverWrite )
   {
    spIXMLDoc.Release();
    return TRUE;
   }
  }
  CComPtr<IXMLDOMProcessingInstruction> spProcessingInstruction;
  CString szTmp;
  szTmp.Format(_T("version=\"1.0\"  encoding=\"%s\""), m_szEncode);
  if ( SUCCEEDED(spIXMLDoc->createProcessingInstruction(
   CComBSTR(_T("xml")), 
   CComBSTR(szTmp), 
   &spProcessingInstruction)) && spProcessingInstruction )
  {
   spIXMLDoc->appendChild(spProcessingInstruction, NULL);
  }
  CComPtr<IXMLDOMComment > spComment;
  spIXMLDoc->createComment(CComBSTR(m_szComment), &spComment);
  spIXMLDoc->appendChild(spComment, NULL);
  CComPtr<IXMLDOMElement> spElementTop;
  spIXMLDoc->createElement(CComBSTR(m_szBodyTag), &spElementTop);
  spIXMLDoc->appendChild(spElementTop, NULL);
  COleVariant vpath(m_szXmlFile);
  if ( FAILED(spIXMLDoc->save(vpath)) )
   return FALSE;
  spIXMLDoc.Release();
  return TRUE;
 }
 BOOL Save()
 {
  USES_CONVERSION;
  assert( m_spxmlDoc );
  COleVariant vpath(m_szXmlFile);
  if ( FAILED(m_spxmlDoc->save(vpath)) )
   return FALSE;
  return TRUE;
 }
 BOOL XmlOperation(
  T& t, 
  XMLOPERATION fOp, 
  list<T>* pAllItemList = NULL,
  BOOL bSave = FALSE)
 {
  USES_CONVERSION;
  /************************************************************************/
  /* Because the first one of the struct is used to find.                 */
  /************************************************************************/
  const XMLNODEINFO* pMap = P::_XMLMap();
  assert ( pMap && pMap[0].szNode != NULL );
  CString szNode = pMap[0].szNode;
  CString szValueType = pMap[0].szValueType;
  assert ( szValueType == _T("CString") );
  if ( fOp == xml_getall && !pAllItemList )
  {
   assert(pAllItemList);
   return FALSE;
  }
  CComPtr<IXMLDOMNode> spNode;
  if ( FAILED(m_spxmlDoc->selectSingleNode(CComBSTR(m_szBodyTag), &spNode)) || spNode == NULL )
   return FALSE;
  CComPtr<IXMLDOMNodeList> spNodeList;
  if ( FAILED(spNode->selectNodes(CComBSTR(m_szItemTag), &spNodeList)) || spNodeList == NULL )
   return FALSE;
  long count = 0;
  spNodeList->get_length(&count);
  BOOL bFind = FALSE;
  CComPtr<IXMLDOMNode> _spNode = NULL;
  for ( int i = 0; i < count; i++ )
  {
   if ( SUCCEEDED(spNodeList->get_item(i, &_spNode)) && _spNode != NULL )
   {
    if ( fOp == xml_getall )
    {
     T t1;
     if ( Get(_spNode, t1) )
      pAllItemList->push_back(t1);
    }
    else
    {
     CComPtr<IXMLDOMNode> __spNode = NULL;
     if ( FAILED(_spNode->selectSingleNode(CComBSTR(szNode), &__spNode)) || __spNode == NULL )
      return FALSE;
     BSTR bstr;
     if ( __spNode )
     {
      __spNode->get_text(&bstr);
      if ( *(CString*)&t == OLE2T(bstr) )
      {
       bFind = TRUE;
       break;
      }
     }
    }
    _spNode.Release();
   }
  }
  if ( fOp == xml_getall )
  {
   return TRUE;
  }
  switch ( fOp )
  {
  case xml_del:
   {
    if ( !bFind )
     return FALSE;
    return ( SUCCEEDED(spNode->removeChild(_spNode, NULL)) && Save() );
   }
   break;
  case xml_add:
  case xml_modify:
   {
    if ( !bFind || fOp != xml_modify )
    {
     CComPtr<IXMLDOMElement> spElement;
     if ( FAILED(m_spxmlDoc->createElement(CComBSTR(m_szItemTag), &spElement)) || spElement == NULL )
      return FALSE;
     if ( FAILED(spNode->appendChild(spElement, NULL)) )
      return FALSE;
     _spNode = spElement;
    }
    return Add(_spNode, t);
   }
   break;
  case xml_getfirstmatch:
   {
    return Get(_spNode, t);
   }
   break;
  default:
   {
    return FALSE;
   }
   break;
  }
  return TRUE;
 }
protected:
 CString m_szXmlFile;
 CComPtr<IXMLDOMDocument> m_spxmlDoc;
 CString m_szItemTag;
 CString m_szBodyTag;
 CString m_szComment;
 CString m_szEncode;
};
#endif  // __XMLFILECOMMON_H__

When you create a new xml file use like this:

 
/*


Contact List XML
ContactListXml.h




*/







#ifndef __CONTACTLISTXML_H__
#define __CONTACTLISTXML_H__

#include "XMLFileCommon.h"
typedef struct tagCONTACTLISTINFO
{
 CString szContactListName;
 CString szDescription;
 CString szContactListPath;
 DWORD  dwContactNum;
 time_t CreateTime;
}CONTACTLISTINFO, *PCONTACTLISTINFO;



class CContactListXml 
 : public CXMLFileCommon<CONTACTLISTINFO, CContactListXml>
{
public:
 CContactListXml() {};
 ~CContactListXml() {};

public:
 BEGIN_XML_MAP()
  XML_MAP(szContactListName, CString, CONTACTLISTINFO)
  XML_MAP(szDescription, CString, CONTACTLISTINFO)
  XML_MAP(szContactListPath, CString, CONTACTLISTINFO)
  XML_MAP(dwContactNum, DWORD, CONTACTLISTINFO)
  XML_MAP(CreateTime, time_t, CONTACTLISTINFO)
 END_XML_MAP()
};




#endif  __CONTACTLISTXML_H__
 CContactListXml xml;
 xml.SetXmlName("C:\\2.xml");
 xml.SetParams("pppasdsdasdp", "UTF-8");
 if ( xml.InitXML() && xml.Load() )
 {
  CONTACTLISTINFO cti;
  cti.szContactListName = _T("我是wak");
  cti.szDescription = _T("Xml很好");
  cti.szContactListPath = _T("你撒谎的哦");
  cti.dwContactNum = 1002;
  cti.CreateTime = 213244;
  
  xml.XmlOperation(cti, CContactListXml::xml_modify);
  xml.XmlOperation(cti, CContactListXml::xml_add);
  list<CONTACTLISTINFO> list1;
  xml.XmlOperation(cti, CContactListXml::xml_findfirstmatch, &list1);
  
  CONTACTLISTINFO d3;
  d3.szContactListName = "pppp3";
  xml.XmlOperation(cti, CContactListXml::xml_findfirstmatch);
 }

I hope this code may help you much. If you have any question can tell me.

wak 2008.3.31 22:05

History

NULL

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

wak1984

Software Developer
PPStream
China China

Member

Wak has been programming professionally for three years now.
 
Worked for ROR SOFT
Worked for www.qihoo.com
Worked for PPstream
 
And... I want to work for MicroSoft someday ^_^


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 31 Mar 2008
Article Copyright 2008 by wak1984
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid