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" ?>
< <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
#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);
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);
return FALSE;
}
BOOL Get(CComPtr<IXMLDOMNode> pNode, T& t)
{
USES_CONVERSION;
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)
{
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;
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;
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
When you create a new xml file use like this:
#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