libxml2库的使用方法,创建和读取xml文件,以及使用中的注意事项

解析和创建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占用变化,保持一个稳定值则说明没有泄漏。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值