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

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

}

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

(0)

相关推荐

  • Linux UDP socket 设置为的非阻塞模式与阻塞模式区别

    Linux UDP socket 设置为的非阻塞模式与阻塞模式区别 UDP socket 设置为的非阻塞模式 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct sockaddr *)&SockAddr,&ScokAddrLen); UDP socket 设置为的阻塞模式 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), 0, (

  • LINUX 查找tomcat日志关键词命令

    #查询catalina.out日志文件中的关键词为2016-04-13 11:26:00的日志信息 grep -C 10 '2016-04-13 11:26:00' catalina.out |more 解释: grep :查询,筛选 -C : grep的-A, -B, -C选项分别可以显示匹配行的后,前,后前多少行内容: 10 :是前后多少行 '2016-04-13 11:26:00' :关键词,注意是单引号包裹 catalina.out : 检索的文件 可以是目录 ./ |more : 这个

  • Linux 中的nc命令小结

    NetCat,在网络工具中有"瑞士军刀"美誉,其有Windows和Linux的版本.因为它短小精悍(1.84版本也不过25k,旧版本或缩减版甚至更小).功能实用,被设计为一个简单.可靠的网络工具,可通过TCP或UDP协议传输读写数据.同时,它还是一个网络应用Debug分析器,因为它可以根据需要创建各种不同类型的网络连接. 一.版本 通常的Linux发行版中都带有NetCat(简称nc),甚至在拯救模式光盘中也由busybox提供了简版的nc工具.但不同的版本,其参数的使用略有差异. N

  • Linux在shell中自动生成1到100的数组方法(两种方法)

    之前自己在写shell脚本的时候,需要自动创建1-100的文本确不知道该如何去创建.百度一翻终于知道了创建的方法. 在shell脚本中创建1-100的方法很多,那我在这里主要就说两种容易理解且方便的方法: 第一种方法: for i in {1..100} do echo $i done 使用{1..100}这种方式简单明了,大家也可以在linux命令模式下直接:echo {1..100}看一下效果. 第二种方法: 使用seq函数 for i in `seq 1 100` do echo $i d

  • Linux服务器下PHPMailer发送邮件失败的问题解决

    需求 更换服务器之后,我发现我的发送邮件功能失效了!原来的服务器是可以的,一定是哪里出问题了,决定来排查一下.我是用的PHPMailer,SMTP方式发送邮件的. 排查过程 这种方式首先PHP要开启sockets拓展,查了一下phpinfo页面,是开启的: 看了一下openssl也是开启(因为拿了qq邮箱来测),所以没问题: 那就再看一下allow_url_fopen,开启的,没问题: 是不是禁用了函数?没有禁用,没问题: 那配置上就没有问题了,我就想,是不是端口被占用了? 运行一下:netst

  • Linux 下安装 memcached 及 memcacheq的方法

    一:安装memcached 1.下载memcached包 下载地址:http://www.memcached.org (最新包就在首页,点击下载就OK)     解压包:# tar -zxvf memcached-1.4.13.tar.gz (根据自身的情况解压到目录)     进入目录:# cd memcached-1.4.13 2.安装libevent 检查一下有没有安装libevent: ls -al /usr/lib |grep libevent     如果没有就安装libevent

  • 详解阿里云LINUX服务器配置HTTPS(NGINX)

    背景说明 服务器为阿里云 ECS,操作系统为 CentOS 6.5. 部署配置说明 第一步,安装nginx 之所以要先安装 nginx,是因为下面配置域名解析的时候可以直接在浏览器看到效果,当然了,先配置域名,然后 ping 一下也是可以的 下载Nginx源码包,解压源码包,进入解压后的目录,编译配置,命令如下: ./configure --prefix=/usr/local/nginx --with-http_ssl_module 以上命令将nginx安装到usr/local/nginx目录下

  • Linux 单个tomcat多实例部署shell脚本详解

    Linux 单个tomcat多实例部署shell脚本详解 步骤: 1. 下载tomcat,解压安装 2.将tomcat下的webapps,conf,temp等目录分别拷至根目录www下A,B,C目录下 3.新建如下脚本restart_tomcat.sh 4.使用restart_tomcat.sh A/B/C #!/bin/sh if [ -z $1 ] then echo "\033[31;1mplease input the app which you need restart...\033[

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

     Linux 下读XML 的类详解及实现代码 在Linux下写程序,常需要读一些配置文件.现有的XML工具很多,可以方便的编辑和生成XML. 但VC中用的XML解析器在Linux下不能用.只好自已写了个.用了一下,还不错. #include <stdio.h> #include <stdlib.h> // ********************************************************************** // // XML解析类(hongh

  • linux下安装solr的教程详解

    安装Solr 第一步:将solr的压缩包上传到Linux系统 第二步:解压tomcat tar -zvxf apache-tomcat-7.0.47.tar.gz [root@localhost ~]# tar -zxvf apache-tomcat-7.0.47.tar.gz 第三步:在/usr/local/新建目录solr 第四步:将tomcat拷贝在/usr/local/solr/目录下,并命名为tomcat 第五步 解压solr [root@localhost ~]# tar -zvxf

  • Java多线程读写锁ReentrantReadWriteLock类详解

    目录 ReentrantReadWriteLock 读读共享 写写互斥 读写互斥 源码分析 写锁的获取与释放 读锁的获取与释放 参考文献 真实的多线程业务开发中,最常用到的逻辑就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务),这样做虽然保证了实例变量的线程安全性,但效率却是非常低下的.所以在JDK中提供了一种读写锁ReentrantReadWriteLock类,使用它可以加快运行效率. 读写锁表示两个锁,一个是读操作相关的锁

  • linux下用户程序同内核通信详解(netlink机制)

    简介 linux下用户程序同内核通信的方式一般有ioctl, proc文件系统,剩下一个就是Netlink套接字了. 这里先介绍下netlink. Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink. Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点: 1,为了使用 netlink,用户仅需要在

  • Linux下的fdisk命令用法详解

    Linux下的fdisk功能是极其强大的,用它可以划分出最复杂的分区,下面简要介绍一下它的用法: 对于IDE硬盘,每块盘有一个设备名:对应于主板的四个IDE接口,设备名依次为:/dev/hda,/dev/hdb,/dev/hdc,/dev/hdd等, 如果还有IDE Raid卡,则依次为:/dev/hde,/dev/hdf,/dev/hdg,/dev/hdh.对于SCSI硬盘,则设备名依次为/dev/sda,/dev/sdb...等等 fdisk的命令行用法为: fdisk 硬盘设备名 进入fd

  • Linux下安装mysql的教程详解

    1. 关闭mysql服务 # service mysqld stop 2. 检查是否有rpm包,如果没有用rpm安装过mysql,不应该有残留,如果有,需要删掉 检查语法: rpm -qa|grep -i mysql 删除语法: rpm -e <包的名字> 如果遇到依赖,无法删除,使用 rpm -e --nodeps <包的名字> 不检查依赖,直接删除rpm包. 3. 通过find命令检查是否有安装mysql文件,有需要删除 检查语法: find / -name mysql 删除语

  • java LinkedList类详解及实例代码

    java  LinkedList类详解 LinkedList的特有功能 A:添加功能 public void addFirst(Object e); public void addLast(Object e); B:特有功能 public Object getFirst(); public Object getLast(); C:删除功能 public Object removeFirst(); public Object removeLast(); 实例代码: import java.util

  • java  LinkedList类详解及实例代码

    java  LinkedList类详解 LinkedList的特有功能 A:添加功能 public void addFirst(Object e); public void addLast(Object e); B:特有功能 public Object getFirst(); public Object getLast(); C:删除功能 public Object removeFirst(); public Object removeLast(); 实例代码: import java.util

  • Linux下重新启动Tomcat的步骤详解

    本文主要介绍的是Linux下重新启动Tomcat的步骤,在Linux系统下,重启Tomcat使用命令操作的! 具体的步骤如下: 首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh 查看Tomcat是否以关闭 ps -ef|grep java 如果显示以下相似信息,说明Tomcat还没有关闭 root 7010 1 0 Apr19 ? 00:30:13 /usr/local/java/bin/java -Dj

  • 如何测试Linux下tcp最大连接数限制详解

    前言 关于TCP服务器最大并发连接数有一种误解就是"因为端口号上限为65535,所以TCP服务器理论上的可承载的最大并发连接数也是65535". 先说结论:对于TCP服务端进程来说,他可以同时连接的客户端数量并不受限于可用端口号.并发连接数受限于linux可打开文件数,这个数是可以配置的,可以非常大,所以实际上受限于系统性能. 现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼"天天提高并发,你自己实现的最高并发是多少"的时候能义正言辞的怼回去,趁着

随机推荐