在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:
char mFrameName[100]; //帧名
int mAttrNum; //属性数量
SXMLAttrib* mAttrArray; //属性数组 SXMLFrame* mpSiblFrame; //兄弟结点
SXMLFrame* mpChiFrame; //子结点
SXMLFrame* mpParentFrame; //父结点
public: SXMLFrame();
~SXMLFrame(); void Release_Depath();
SXMLFrame* GetFrame_Depth(char *szFrameName);
int GetChildNum();
SXMLFrame* GetChildFrame(int Index);
SXMLFrame* GetChildFrame(char *szFrameName);
SXMLFrame* GetSiblFrame();
SXMLFrame* GetParentFrame();
SXMLAttrib* GetAttrib(char *szKeyName);
bool ParseAttrString(char *szXMLString);
}
;
class CXMLFile
{
SXMLFrame mRoot;
SXMLFrame* mpCurrentFrame;
bool mbDepthClose; //闭合
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;
}
int SXMLFrame::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);
}