解析和创建xml的示例代码
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
typedef struct _PC2PPC_CMD_Record
{
char DeviceNum[100];
char CMDNum[100];
char CMDDescribe[100];
int Num;
int Size;
}PC2PPC_CMD_Record;
//保存文件
int SaveXmlFile(char *FileName,xmlDocPtr doc,char *encoding);
//创建xml文件,并设置根节点
xmlNodePtr CreateXml(char *RootNodeName,xmlDocPtr doc);
//添加子节点
xmlNodePtr AddXmlChlid(xmlNodePtr FatherNode,char *ChildNodeName);
//添加属性
void AddXmlProp(xmlNodePtr Node,char *name,char *val);
//添加内容
xmlNodePtr AddContent(xmlNodePtr Node,char *val);
//字符串转int
int Strtoi(char *str);
//int转字符串
int ItoStr(char *str, int val);
//读文件
int ReadRecordXml(PC2PPC_CMD_Record *CMD, char *filename );
//写文件
int CreateRecordStopXML( PC2PPC_CMD_Record CMD , char *filename );
int main()
{
PC2PPC_CMD_Record CmdHead;
while(1)
{
ReadRecordXml( &CmdHead , "/home/sjn/app/testMianshiti/Record_stop.xml" );
CreateRecordStopXML( CmdHead , "/home/sjn/app/testMianshiti/CreateXMl.xml" );
}
return 0;
}
int ReadRecordXml(PC2PPC_CMD_Record *CMD, char *filename )
{
//是否成功收到
const char* name;
char* content;
xmlDocPtr doc = NULL;
xmlNodePtr cur = NULL;//node to be get
xmlChar* szKey;
const char *docname = filename;
xmlKeepBlanksDefault(0);
doc = xmlParseFile(docname);
if(doc == NULL){
printf("Document not parse successfully!!!");
xmlFreeDoc(doc);
}
//根节点为cur
cur = xmlDocGetRootElement(doc);
if(cur == NULL){
printf("doc is empty");
xmlFreeDoc(doc);
}
printf("根节点为 :%s\n",cur->name);
cur = cur->xmlChildrenNode->xmlChildrenNode;
//读根节点的子节点的子节点中名为编号的值
szKey = xmlGetProp(cur,(const xmlChar*)"编号");
printf("编号 :%s\n",(char *)szKey);
strcpy( CMD->DeviceNum , (char *)szKey );
xmlFree(szKey);
szKey = xmlGetProp(cur,(const xmlChar*)"命令");
printf("命令 :%s\n",(char *)szKey);
strcpy( CMD->CMDNum , (char *)szKey );
xmlFree(szKey);
szKey = xmlGetProp(cur,(const xmlChar*)"描述");
printf("描述 :%s\n",(char *)szKey);
strcpy( CMD->CMDDescribe , (char *)szKey );
xmlFree(szKey);
cur = cur->xmlChildrenNode;
szKey = xmlGetProp(cur,(const xmlChar*)"名称");
content = (char *)xmlNodeGetContent(cur);
CMD->Num = Strtoi((char *)content);
printf("名称 :%s %s %d\n",(char *)szKey,content,CMD->Num );
xmlFree(szKey);
free(content);
//当前节点等于它的下一个同级节点
cur = cur->next;
szKey = xmlGetProp(cur,(const xmlChar*)"名称");
content = (char *)xmlNodeGetContent(cur);
CMD->Size = ( unsigned int )Strtoi((char *)content);
printf("名称 :%s %s %d\n",(char *)szKey,content,CMD->Size );
xmlFree(szKey);
free(content);
printf( "解析完成\n");
xmlFreeDoc(doc);
return 1;
}
int CreateRecordStopXML( PC2PPC_CMD_Record CMD , char *filename )
{
xmlNodePtr RootNode,NewNode,ProNode;
char *str = (char *)malloc(100);
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); //定义文档和节点指针
if(doc == NULL)
{
printf( "doc create ERROR!!!\n");
xmlFreeDoc(doc);
return 0;
}
RootNode = CreateXml("监控服务",doc);
ProNode = AddXmlChlid(RootNode,"监控信息");
NewNode = AddXmlChlid(ProNode,"控制命令");
AddXmlProp(NewNode,"编号",CMD.DeviceNum);
AddXmlProp(NewNode,"命令",CMD.CMDNum);
AddXmlProp(NewNode,"描述",CMD.CMDDescribe);
ProNode = NewNode;
NewNode = AddXmlChlid(ProNode,"参数");
AddXmlProp(NewNode,"名称","任务编号");
ItoStr(str,CMD.Num);
AddContent(NewNode,str);
NewNode = AddXmlChlid(ProNode,"参数");
AddXmlProp(NewNode,"名称","任务大小");
ItoStr(str,CMD.Size);
AddContent(NewNode,str);
char *encoding = "UTF-8";
SaveXmlFile(filename,doc,encoding);
xmlFreeDoc(doc);
free(str);
return 1;
}
int Strtoi(char *str)
{
return atoi(str);
}
int ItoStr(char *str, int val)
{
return snprintf(str ,10, "%d" , val);
}
int SaveXmlFile(char *FileName,xmlDocPtr doc,char *encoding)
{
int nRel =xmlSaveFormatFileEnc(FileName,doc,encoding,1);
if (nRel != -1)
{
printf("XML Create success\n");
return 1;
}
else
{
printf( "XML Create Error!!! nRel = %d\n",nRel);
return 0;
}
//释放文档内节点动态申请的内存
xmlFreeDoc(doc);
}
xmlNodePtr CreateXml(char *RootNodeName,xmlDocPtr doc)
{
char *encoding = "UTF-8";
xmlNodePtr RootNode = xmlNewNode(NULL,BAD_CAST RootNodeName);
xmlDocSetRootElement(doc,RootNode); //设置根节点
return RootNode;
}
xmlNodePtr AddXmlChlid(xmlNodePtr FatherNode,char *ChildNodeName)
{
xmlNodePtr ChildNode = xmlNewNode(NULL,BAD_CAST ChildNodeName);
xmlAddChild(FatherNode,ChildNode);
return ChildNode;
}
void AddXmlProp(xmlNodePtr Node,char *name,char *val)
{
xmlNewProp(Node,BAD_CAST name,BAD_CAST val);
}
xmlNodePtr AddContent(xmlNodePtr Node,char *val)
{
xmlNodePtr content = xmlNewText(BAD_CAST val);
xmlAddChild(Node,content);
return content;
}
Record_stop.xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<监控服务>
<监控信息>
<控制命令 编号="123" 命令="456" 描述="结束任务参数">
<参数 名称="任务编号">12345678</参数>
<参数 名称="任务大小">456</参数>
</控制命令>
</监控信息>
</监控服务>
这是xml解析和创建的示例代码,其中要注意的部分是使用完了doc之后,要调用xmlFreeDoc(doc),可以释放所有该doc分配的空间,比如xmlChar *,xmlNodePtr。不包括调用函数分配的空间,所以这部分还要记得手动释放,主要就是xmlGetProp这个函数,每调用一次就要记得释放一次,例如:
szKey = xmlGetProp(cur,(const xmlChar*)"命令");
printf("命令 :%s\n",(char *)szKey);
strcpy( CMD->CMDNum , (char *)szKey );
xmlFree(szKey);
使用库编程之后一定要记得测试是否有内存泄露,否则对后期的调试会造成很大影响。
编译: gcc main.c -I /usr/local/include/libxml2/ -lxml2 -lpthread
只加lxml库是不够的因为libxml2库中使用了lpthread,所以也要加上这个库
运行:./a.out >>log.file 2>&1 &
把程序的标准输出和标准错误追加到log.file中(& 表示等同于的意思,2>&1,表示2的输出重定向等同于1,0标准输入,1标准输出,2标准错误),并后台运行,然后输入top观察mem占用变化,保持一个稳定值则说明没有泄漏。