在Linux下写程序,常需要读一些配置文件。现有的XML工具很多,可以方便的编辑和生成XML。
但VC中用的XML解析器在Linux下不能用。只好自已写了个。用了一下,还不错。
#include <stdio.h>
#include <stdlib.h>
// ********************************************************************** //
// XML解析类(honghaier写于2008-11-19)
// ********************************************************************** //
struct SXMLAttrib
{
char mKeyName[100];//键名
char mValue[100];//键值
}
;
struct SXMLFrame
{
public:
charmFrameName[100];//帧名
intmAttrNum;//属性数量
SXMLAttrib*mAttrArray;//属性数组
SXMLFrame*mpSiblFrame;//兄弟结点
SXMLFrame*mpChiFrame;//子结点
SXMLFrame* mpParentFrame;//父结点
public:
SXMLFrame();
~SXMLFrame();
voidRelease_Depath();
SXMLFrame*GetFrame_Depth(char *szFrameName);
intGetChildNum();
SXMLFrame*GetChildFrame(int Index);
SXMLFrame*GetChildFrame(char *szFrameName);
SXMLFrame*GetSiblFrame();
SXMLFrame*GetParentFrame();
SXMLAttrib* GetAttrib(char *szKeyName);
bool ParseAttrString(char *szXMLString);
}
;
class CXMLFile
{
SXMLFramemRoot;
SXMLFrame*mpCurrentFrame;
boolmbDepthClose;//闭合
private:
bool ParseFrameString(char *szXMLString);
public:
int pFile;
CXMLFile();
~CXMLFile();
void Close();
void Release();
bool Open( const char * pFileName);
SXMLFrame* GetRoot();
SXMLFrame* GetFrame_Depth(char *szFrameName);
}
;
//====================================================
SXMLFrame::SXMLFrame()
{
memset(mFrameName,0,sizeof(mFrameName));
mAttrNum = 0;
mAttrArray = NULL;
mpSiblFrame = NULL;
mpChiFrame = NULL;
mpParentFrame = NULL;
}
SXMLFrame::~SXMLFrame()
{
Release_Depath();
}
void SXMLFrame::Release_Depath()
{
if(mAttrNum > 0)
{
if(mAttrArray)
{
delete[] mAttrArray;
mAttrArray = NULL;
}
mAttrNum = 0;
}
if(mpChiFrame)
{
mpChiFrame->Release_Depath();
delete mpChiFrame;
mpChiFrame = NULL;
}
if(mpSiblFrame)
{
mpSiblFrame->Release_Depath();
delete mpSiblFrame;
mpSiblFrame = NULL;
}
}
SXMLFrame*SXMLFrame::GetFrame_Depth(char *szFrameName)
{
if(strcmp(mFrameName,szFrameName)==0)
{
return this;
}
if(mpChiFrame)
{
SXMLFrame* tResFrame = mpChiFrame->GetFrame_Depth(szFrameName);
if(tResFrame)return tResFrame;
}
if(mpSiblFrame)
{
SXMLFrame* tResFrame = mpSiblFrame->GetFrame_Depth(szFrameName);
if(tResFrame)return tResFrame;
}
return NULL;
}
intSXMLFrame::GetChildNum()
{
int count = 0;
for(SXMLFrame *temp = mpChiFrame ; temp != NULL ;temp = temp->mpSiblFrame)
{
count++;
}
return count;
}
SXMLFrame*SXMLFrame::GetChildFrame(int Index)
{
int count = 0;
for(SXMLFrame *temp = mpChiFrame ; temp != NULL ;temp = temp->mpSiblFrame)
{
if(count == Index)return temp;
count++;
}
return NULL;
}
SXMLFrame*SXMLFrame::GetChildFrame(char *szFrameName)
{
for(SXMLFrame *temp = mpChiFrame ; temp != NULL ;temp = temp->mpSiblFrame)
{
if(strcmp(temp->mFrameName,szFrameName)==0)
{
return temp;
}
}
return NULL;
}
SXMLFrame*SXMLFrame::GetSiblFrame()
{
return mpSiblFrame;
}
SXMLFrame*SXMLFrame::GetParentFrame()
{
return mpParentFrame;
}
SXMLAttrib* SXMLFrame::GetAttrib(char *szKeyName)
{
for(int i = 0 ; i < mAttrNum ; i++)
{
if(strcmp(mAttrArray[i].mKeyName,szKeyName)==0)
{
return &mAttrArray[i];
}
}
return NULL;
}
bool SXMLFrame::ParseAttrString(char *szXMLString)
{
SXMLAttrib AttribArray[100];
int len = strlen(szXMLString);
mAttrNum = 0;
int StrPos = 0;
bool HaveFrameName = false;
for(int i = 0 ;i < len ; i++)
{
if(i==(len-1))
{
if(false == HaveFrameName)
{
memcpy(mFrameName,szXMLString,len);
mFrameName[len]='/0';
HaveFrameName = true;
}
else
{
if(( len - StrPos-1 )== 0)
{
memset(AttribArray[mAttrNum].mValue,0,sizeof(AttribArray[mAttrNum].mValue));
}
else
{
memcpy(AttribArray[mAttrNum].mValue,szXMLString+StrPos,len-StrPos-1);
AttribArray[mAttrNum].mValue[len-StrPos-1]='/0';
}
mAttrNum++;
StrPos = 0;
}
break;
}
if(szXMLString[i] == ' '&&szXMLString[i-1] == ' ')
{
StrPos = i+1;
continue;
}
if(szXMLString[i] == ' ')
{
if(false == HaveFrameName)
{
memcpy(mFrameName,szXMLString,i);
mFrameName[i]='/0';
HaveFrameName = true;
StrPos = i+1;
continue;
}
else
{
if(( i - StrPos-1 )== 0)
{
memset(AttribArray[mAttrNum].mValue,0,sizeof(AttribArray[mAttrNum].mValue));
}
else
{
memcpy(AttribArray[mAttrNum].mValue,szXMLString+StrPos,i-StrPos-1);
AttribArray[mAttrNum].mValue[i-StrPos-1]='/0';
}
mAttrNum++;
StrPos = i+1;
continue;
}
}
if(szXMLString[i] == '=')
{
memcpy(AttribArray[mAttrNum].mKeyName,szXMLString+StrPos,i-StrPos);
AttribArray[mAttrNum].mKeyName[i-StrPos]='/0';
i++;//跳过一个"""
StrPos = i+1;
continue;
}
}
mAttrArray = new SXMLAttrib[mAttrNum];
if(!mAttrArray)return false;
memcpy(mAttrArray,AttribArray,mAttrNum*sizeof(SXMLAttrib));
return true;
}
CXMLFile::CXMLFile()
{
pFile = 0;
mpCurrentFrame = NULL;
mbDepthClose = false;
}
CXMLFile::~CXMLFile()
{
Close();
}
void CXMLFile::Close()
{
if( pFile>0)
{
int error = close( pFile);
if( error!=0)
{
perror("close file failed");
}else
{
pFile=-1;
}
Release();
}
}
void CXMLFile::Release()
{
mRoot.Release_Depath();
}
bool CXMLFile::Open( const char * pFileName)
{
pFile =0;
pFile = open( pFileName,O_RDONLY);
if( pFile==-1)
{
perror(pFileName);
return false;
}
int num = 0;
char buffer;
bool bReadXMLString = false;
int XMLStringNum = 0;
char XMLString[1024];
while(num = read(pFile,&buffer,1)>0)
{
if(buffer =='<')
{
bReadXMLString = true;
XMLStringNum = 0;
continue;
}
if(buffer == '>')
{
XMLString[XMLStringNum]='/0';
if( false == ParseFrameString(XMLString))
{
printf("Read XML error: %s /n",XMLString);
return false;
}
bReadXMLString = false;
continue;
}
if(true == bReadXMLString)
{
XMLString[XMLStringNum++] = buffer;
}
}
mpCurrentFrame = NULL;
mbDepthClose = true;
return true;
}
SXMLFrame* CXMLFile::GetRoot()
{
return &mRoot;
}
SXMLFrame* CXMLFile::GetFrame_Depth(char *szFrameName)
{
return mRoot.GetFrame_Depth(szFrameName);
}
bool CXMLFile::ParseFrameString(char *szXMLString)
{
if(szXMLString[0] == '?')return true;
if(szXMLString[0] == '!')return true;
if(szXMLString[0] == '/')
{
//如果是结束
mpCurrentFrame = mpCurrentFrame->GetParentFrame();
mbDepthClose = true;
}
else
{
mbDepthClose = false;
if( NULL == mpCurrentFrame)
{
mpCurrentFrame = &mRoot;
}
SXMLFrame* tNewFrame = new SXMLFrame;
tNewFrame->ParseAttrString(szXMLString);
if(false == mbDepthClose)
{
tNewFrame->mpParentFrame = mpCurrentFrame;
if( NULL == mpCurrentFrame->mpChiFrame)
{
mpCurrentFrame->mpChiFrame = tNewFrame;
}
else
{
for(SXMLFrame *temp = mpCurrentFrame->mpChiFrame ; temp != NULL ;temp = temp->mpSiblFrame)
{
if( NULL == temp->mpSiblFrame)
{
temp->mpSiblFrame = tNewFrame;
break;
}
}
}
mpCurrentFrame = tNewFrame;
}
else
{
tNewFrame->mpParentFrame = mpCurrentFrame->GetParentFrame();
mpCurrentFrame->mpSiblFrame = tNewFrame;
mpCurrentFrame = tNewFrame;
}
}
return true;
}
用XML工具做了一个简单的XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XML Explorer v2.0 by Mergesoft (www.mergesoft.com)-->
<root>
<Honghaier Name="红孩儿" Age="26"></Honghaier>
</root>
========================================================
在C++代码中
可以这样使用
CXMLFile xmlfile;
xmlfile.Open("1.xml");
SXMLFrame* mRootFrame = CXMLFile::GetRoot();
int ChildNum = mRootFrame->GetChildNum();
for(int i = 0 ; i < ChildNum; i++)
{
SXMLFrame* tChileFrame = mRootFrame ->GetChildFrame (i);
SXMLAttrib* tAttrib = tChileFrame->GetAttrib("Age");
print("%s : %s= %s /n",mChileFrame ->mFrameName,tAttrib->mKeyName,tAttrib->mValue);
}