欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

Linux 下读XML 的类详解及实现代码

程序员文章站 2023-03-25 11:46:24
 linux 下读xml 的类详解及实现代码 在linux下写程序,常需要读一些配置文件。现有的xml工具很多,可以方便的编辑和生成xml。 但vc中用的xm...

 linux 下读xml 的类详解及实现代码

在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);

}

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!