有一些类别,每一类都包含了一些物品,想用以下的XML保存。
数据样例如下:
<Actors>
<FileVersion>0.2</FileVersion>
<Category>
<CateName>未分类sdf</CateName>
<Act>
<ActName>地板</ActName>
<ActId>101</ActId>
<File>floor</File>
<Pic></Pic>
<Des>地板</Des>
</Act>
<Act>
<ActName>怪物</ActName>
<ActId>203</ActId>
<File>mon31</File>
<Pic></Pic>
<Des>怪物</Des>
</Act>
</Category>
</Actors>
我设计了如下的类:
//ActorCategory.hpp
#ifndef __ACTOR_CATEGORY_HPP__
#define __ACTOR_CATEGORY_HPP__
#include <string>
#include <list>
#include <map>
#ifndef DWORD
#define DWORD unsigned long
#endif
using namespace std;
/**
* 每一个具体的物件信息
*/
struct SActInfo
{
SActInfo():
dwActId(0)
{
}
DWORD dwActId;
string strFileName;
string strPicName;
string strDescribe; //描述
};
typedef pair<string, struct SActInfo*> PairAct;
typedef map<string, struct SActInfo*> MapAct;
typedef pair<string, MapAct*> PairCate;
typedef map<string, MapAct*> MapCate;
/**
* 物件类别
*/
class CActorCategory
{
public:
CActorCategory();
CActorCategory(const CActorCategory &rcActorCate);
~CActorCategory();
// bool Init(CEditorFrame *pFrame);
bool InsertCate(const string &strCate); //插入物品类别strCate1
void UpdateCateName(const string &strOldCate, const string &strNewCate); //更新类别的名称为strNewCate1
bool DeleteCate(int index);
bool DeleteCate(const string &strCateName); //删除类别
//将物件strActor从类别strSrcCateName中移入类别strDestCateName中
bool MoveTo(const string &strDestCateName, const string &strSrcCateName, const string &strActorName);
bool InsertActor(const string &strCateName, const string &strActorName, SActInfo* pActInfo);
//bool InsertActor(const string &strCateName, const string &strActorName, const string &strFileName=""); //将物件添加到类别中,物件指定了文件名
bool SetActorFile(const string &strCateName, const string &strActorName, const string &strFileName); //给物件指定一个对应的文件
void UpdateActor(const string &strCateName, const string &strOldActor, const string &strNewActor); //更新物件的名称
bool DeleteActor(const string &strCateName, const string &strActorName); //将物件strActor从类别strCate中删除
DWORD GetActorIdByName(const string &strActorName);
void GetCategoryString(list<string> & lstRes); //返回所有的分类信息名称
void GetActorString(const string &strCate1, list<string> &lstRes); //返回某一分类的所有物件
// SActorInfoRes* GetActorInfoByName(const string &strActorName);
// SActorInfoRes* GetActorInfoByFileName(const string &strFileName);
bool RebuldFromServer();
bool UpdateFromServer();
bool LoadFromXML(const string &strFileName); //读取分类信息文件
bool SaveToXML(const string &strFileName = "GameActors.xml"); //保存
CActorCategory& operator=(const CActorCategory& rcActorCate);
private:
void Clear();
bool HasFile(const string& strFileName);
map<string, map<string, struct SActInfo*>*> m_mCategoryInfo; //类别,类别名作为索引,第二个元素用物件名作索引
};
#endif
//ActorCategory.cpp
#include "ActorCategory.hpp"
#include <iostream>
#include <fstream>
#include <strstream>
#include "Markup.h"
#include "ActorTable.hpp"
#define KEY_TAB (char)0x9
#define TABLE_FILE "table/Wi_ActorInfo.csv"
//#include "rtc2_text_xml.h"
/**
* the constructor
*/
CActorCategory::CActorCategory()
{
}
CActorCategory::CActorCategory(const CActorCategory &rcActorCate1)
{
struct SActInfo* psActorInfoCopy = new SActInfo();
MapAct* pmActorCopy = new MapAct();
MapAct* pmActorTemp;
MapCate::const_iterator ite = rcActorCate1.m_mCategoryInfo.begin();
MapCate::const_iterator end = rcActorCate1.m_mCategoryInfo.end();
for( ; ite!=end; ++ite)
{
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
psActorInfoCopy->dwActId = (iteAc->second)->dwActId;
psActorInfoCopy->strDescribe = (iteAc->second)->strDescribe;
psActorInfoCopy->strFileName = (iteAc->second)->strFileName;
psActorInfoCopy->strPicName = (iteAc->second)->strPicName;
pmActorCopy->insert(PairAct(iteAc->first, psActorInfoCopy));
}
this->m_mCategoryInfo.insert(PairCate(ite->first, pmActorCopy));
}
}
CActorCategory& CActorCategory::operator=(const CActorCategory& rcActorCate1)
{
if (this == &rcActorCate1)
{
return *this; // identity test: if a self-assignment
}
MapAct* pmActorTemp;
MapCate::const_iterator ite = rcActorCate1.m_mCategoryInfo.begin();
MapCate::const_iterator end = rcActorCate1.m_mCategoryInfo.end();
for( ; ite!=end; ++ite)
{
MapAct* pmActorCopy = new MapAct();
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
struct SActInfo* psActorInfoCopy = new SActInfo();
psActorInfoCopy->dwActId = (iteAc->second)->dwActId;
psActorInfoCopy->strDescribe = (iteAc->second)->strDescribe;
psActorInfoCopy->strFileName = (iteAc->second)->strFileName;
psActorInfoCopy->strPicName = (iteAc->second)->strPicName;
pmActorCopy->insert(PairAct(iteAc->first, psActorInfoCopy));
}
this->m_mCategoryInfo.insert(PairCate(ite->first, pmActorCopy));
}
return *this;
}
/**
* the destuctor
*/
CActorCategory::~CActorCategory()
{
MapAct* pmActorTemp;
MapCate::iterator ite = m_mCategoryInfo.begin();
MapCate::iterator end = m_mCategoryInfo.end();
for( ; ite!=m_mCategoryInfo.end(); ++ite)
{
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
delete iteAc->second;
}
delete pmActorTemp;
}
m_mCategoryInfo.clear();
}
void CActorCategory::Clear()
{
MapAct* pmActorTemp;
MapCate::iterator ite = m_mCategoryInfo.begin();
MapCate::iterator end = m_mCategoryInfo.end();
for( ; ite!=m_mCategoryInfo.end(); ++ite)
{
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
delete iteAc->second;
}
delete pmActorTemp;
}
m_mCategoryInfo.clear();
}
/**
* 新增物品类别
*/
bool CActorCategory::InsertCate(const string &strCate) //将类别strCate1插入
{
m_mCategoryInfo.insert(PairCate(strCate,new MapAct()));
return true;
}
/**
* 更新类别的名称为strNewCate1
*/
void CActorCategory::UpdateCateName(const string &strOldCate, const string &strNewCate)
{
if (strNewCate != strOldCate)
{
MapCate::iterator itFind = m_mCategoryInfo.find(strOldCate);
if (itFind != m_mCategoryInfo.end())
{
m_mCategoryInfo.insert(PairCate(strNewCate, itFind->second));
m_mCategoryInfo.erase(strOldCate);
}
}
}
/**
* 删除类别
*/
bool CActorCategory::DeleteCate(int index)
{
MapAct* pmActorTemp;
int i = 0;
MapCate::iterator end = m_mCategoryInfo.end();
for(MapCate::iterator ite = m_mCategoryInfo.begin(); ite!=end; ++ite)
{
if(i == index)
{
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
delete iteAc->second;
}
delete pmActorTemp;
m_mCategoryInfo.erase(ite);
return true;
}
++i;
}
return false;
}
/**
* 删除类别
*/
bool CActorCategory::DeleteCate(const string &strCateName)
{
MapCate::iterator ite = m_mCategoryInfo.find(strCateName);
MapAct* pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
delete iteAc->second;
}
delete pmActorTemp;
m_mCategoryInfo.erase(ite);
return true;
}
/**
* 将物件strActorName从类别strSrcCateName中移入类别strDestCateName中
*/
bool CActorCategory::MoveTo(const string &strDestCateName, const string &strSrcCateName, const string &strActorName)
{
if(strDestCateName == strSrcCateName)
{
return false;
}
MapCate::iterator itSrcCate = m_mCategoryInfo.find(strSrcCateName);
MapCate::iterator itDescCate = m_mCategoryInfo.find(strDestCateName);
MapCate::iterator itEndCate = m_mCategoryInfo.end();
if ((itSrcCate == itEndCate) || (itDescCate == itEndCate))
{
return false;
}
MapAct* pmActorSrc = itSrcCate->second;
MapAct::iterator itSrcAct = pmActorSrc->find(strActorName);
if (itSrcAct == pmActorSrc->end())
{
return false;
}
itDescCate->second->insert(PairAct(strActorName, itSrcAct->second));
pmActorSrc->erase(strActorName);
return true;
}
bool CActorCategory::InsertActor(const string &strCateName, const string &strActorName, SActInfo* pActInfo)
{
MapCate::iterator iteCate = m_mCategoryInfo.find(strCateName);
MapCate::iterator iteEnd = m_mCategoryInfo.end();
if(iteCate == iteEnd)
{
InsertCate(strCateName);
}
iteCate = m_mCategoryInfo.find(strCateName);
assert(iteCate!=iteEnd);
MapAct* pmActorTemp = iteCate->second;
pmActorTemp->insert(PairAct(strActorName, pActInfo));
return true;
}
/*
bool CActorCategory::InsertActor(const string &strCate1, const string &strActorName) //将物件添加到类别中
{
MapActor* pmActorTemp = m_mCategoryInfo.find(strCate1)->second;
return pmActorTemp->insert(PairActor(strActorName, new SActorInformation()));
}
*/
void CActorCategory::UpdateActor(const string &strCateName, const string &strOldActor, const string &strNewActor) //更新物件的名称
{
MapCate::iterator ite = m_mCategoryInfo.find(strCateName);
if (ite != m_mCategoryInfo.end())
{
MapAct* pmActorTemp = ite->second;
MapAct::iterator itAct = pmActorTemp->find(strOldActor);
if ((itAct != pmActorTemp->end()) && (strNewActor != strOldActor))
{
pmActorTemp->insert(PairAct(strNewActor, itAct->second));
pmActorTemp->erase(strOldActor);
}
}
}
DWORD CActorCategory::GetActorIdByName(const string &strActorName)
{
MapAct* pmActorTemp;
MapCate::iterator end = m_mCategoryInfo.end();
for(MapCate::iterator ite = m_mCategoryInfo.begin(); ite!=end; ++ite)
{
pmActorTemp = ite->second;
MapAct::iterator iteFind = pmActorTemp->find(strActorName);
if(iteFind != pmActorTemp->end())
{
return (iteFind->second)->dwActId;
}
}
return 0;
}
/**
* 返回所有的分类信息名称
*/
void CActorCategory::GetCategoryString(list<string> & lstRes)
{
MapCate::iterator ite = m_mCategoryInfo.begin();
MapCate::iterator end = m_mCategoryInfo.end();
for( ; ite!=end; ++ite)
{
lstRes.push_back(ite->first);
}
}
void CActorCategory::GetActorString(const string &strCate1, list<string> &lstRes) //返回某一分类的所有物件
{
MapAct* pmActorTemp = (m_mCategoryInfo.find(strCate1))->second;
MapAct::iterator iteA = pmActorTemp->begin();
MapAct::iterator end = pmActorTemp->end();
for( ; iteA!=end; ++iteA)
{
lstRes.push_back(iteA->first);
}
}
bool CActorCategory::RebuldFromServer()
{
Clear();
CActorTable actTable;
actTable.LoadTable(TABLE_FILE);
MapTable* pTable = actTable.GetTable();
struct SActTable* psActTable;
struct SActInfo* psActInfo;
for(MapTable::iterator ite=pTable->begin(); ite!=pTable->end(); ++ite)
{
psActTable = ite->second;
psActInfo = new SActInfo();
psActInfo->dwActId = psActTable->dwActId;
psActInfo->strFileName = psActTable->strFileName;
psActInfo->strDescribe = psActTable->strDescribe;
InsertActor("未分类", psActTable->strActName, psActInfo);
}
return true;
}
bool CActorCategory::UpdateFromServer()
{
CActorTable actTable;
actTable.LoadTable(TABLE_FILE);
MapTable* pTable = actTable.GetTable();
struct SActTable* psActTable;
struct SActInfo* psActInfo;
string strFileName;
for(MapTable::iterator ite=pTable->begin(); ite!=pTable->end(); ++ite)
{
psActTable = ite->second;
strFileName = psActTable->strFileName;
if(!HasFile(strFileName))
{
psActInfo = new SActInfo();
psActInfo->dwActId = psActTable->dwActId;
psActInfo->strFileName = psActTable->strFileName;
psActInfo->strDescribe = psActTable->strDescribe;
InsertActor("未分类", psActTable->strFileName, psActInfo);
}
}
return true;
}
bool CActorCategory::HasFile(const string& strFileName)
{
SActInfo* psAct;
MapAct* pmActorTemp;
MapCate::iterator ite = m_mCategoryInfo.begin();
MapCate::iterator end = m_mCategoryInfo.end();
for( ; ite!=m_mCategoryInfo.end(); ++ite)
{
pmActorTemp = ite->second;
for(MapAct::iterator iteAc=pmActorTemp->begin(); iteAc!=pmActorTemp->end(); ++iteAc)
{
psAct = iteAc->second;
if(psAct->strFileName == strFileName)
{
return true;
}
}
}
return false;
}
/**
* 供测试用
*//*
bool CActorCategory::LoadFromXML(const string &strFileName)
{
MapAct* pmActorTemp = new map<string, struct SActInfo*>();
pmActorTemp->insert( PairAct("Tom",new struct SActInfo()) );
pmActorTemp->insert( PairAct("Jim",new struct SActInfo()) );
m_mCategoryInfo.insert(PairCate("人物",pmActorTemp));
delete pmActorTemp;
return true;
}
*/
bool CActorCategory::LoadFromXML(const string &strFileName)
{
Clear();
string strInfo;
string strFileFullName=strFileName;
if(strFileFullName.empty())
{
strFileFullName = "ActCate.xml";
}
ifstream ifs(strFileFullName.c_str()); //
char buf[1024] = {0};
while(ifs.good())
{
ifs.getline(buf, sizeof(buf));
strInfo.append(buf);
}
//cout<<strInfo.c_str()<<endl;
CMarkup xml;
xml.SetDoc( (strInfo.c_str()) );
while ( xml.FindChildElem("Category") )
{
MapAct* pmActorTemp = new MapAct();
xml.IntoElem();
xml.FindChildElem( "CateName" );
string strCateName1 = xml.GetChildData();
while(xml.FindChildElem("Act"))
{
xml.IntoElem();
xml.FindChildElem("ActName");
string strActorName1 = xml.GetChildData();
xml.FindChildElem("ActId");
string strActId1 = xml.GetChildData();
xml.FindChildElem("File");
string strFileName1 = xml.GetChildData();
xml.FindChildElem("Pic");
string strPic1 = xml.GetChildData();
xml.FindChildElem("Des");
string strDes1 = xml.GetChildData();
struct SActInfo* pSActInfo1 = new SActInfo();
pSActInfo1->dwActId = atol(strActId1.c_str());
pSActInfo1->strFileName = strFileName1;
pSActInfo1->strPicName = strPic1;
pSActInfo1->strDescribe = strDes1;
pmActorTemp->insert( PairAct(strActorName1,pSActInfo1) );
xml.OutOfElem();
//cout<<strActorName1<<endl;
}
m_mCategoryInfo.insert( PairCate(strCateName1, pmActorTemp) );
xml.OutOfElem();
}
return true;
}
bool CActorCategory::SaveToXML(const string &strFileName/*="GameActors.xml"*/)
{
ostrstream strInfo;
string strFileFullName=strFileName;
if(strFileFullName.empty())
{
strFileFullName = "GameActors.xml";
}
ofstream out(strFileFullName.c_str());//生成文件输出流
strInfo<<"<Actors>"<<endl;
strInfo<<"<FileVersion>0.2</FileVersion>"<<endl<<endl;
MapAct* pmActorTemp;
MapCate::iterator ite = m_mCategoryInfo.begin();
MapCate::iterator end = m_mCategoryInfo.end();
for( ; ite!=end; ++ite)
{
strInfo<<"<Category>"<<endl;
strInfo<<(char)0x9<<"<CateName>";
strInfo<<ite->first.c_str();
strInfo<<"</CateName>"<<endl;
pmActorTemp = ite->second;
for(MapAct::iterator ite2 = pmActorTemp->begin(); ite2!=pmActorTemp->end(); ++ite2)
{
strInfo<<(char)0x9<<"<Act>"<<endl;
strInfo<<(char)0x9<<(char)0x9<<"<ActName>";
strInfo<<ite2->first.c_str();
strInfo<<"</ActName>"<<endl;
strInfo<<(char)0x9<<(char)0x9<<"<ActId>";
strInfo<<(ite2->second)->dwActId;
strInfo<<"</ActId>"<<endl;
strInfo<<(char)0x9<<(char)0x9<<"<File>";
strInfo<<(ite2->second)->strFileName.c_str();
strInfo<<"</File>"<<endl;
strInfo<<(char)0x9<<(char)0x9<<"<Pic>";
strInfo<<(ite2->second)->strPicName.c_str();
strInfo<<"</Pic>"<<endl;
strInfo<<(char)0x9<<(char)0x9<<"<Des>";
strInfo<<(ite2->second)->strDescribe.c_str();
strInfo<<"</Des>"<<endl;
strInfo<<(char)0x9<<"</Act>"<<endl;
}
strInfo<<"</Category>"<<endl<<endl;
}
strInfo<<"</Actors>"<<endl;
strInfo<<'\0';
out<<strInfo.str();
//cout<<strInfo.str();
return true;
}