C++读写XML文件(Libxml2库)
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
C++程序有时候要读写XML文件, 这里介绍一个读写XML文件的库——Libxml2。
主页:http://xmlsoft.org/index.html
入门教程很详细的:http://jianlee.ylinux.org/Computer/C/libxml.html#sec11
读取节点内容的话用XPath方式比较好,要问XPath与Libxml2库之间的关系,有个很形象的比喻:
那就是SQL与数据库之间的关系。
下面的代码是在Linux下实现的:
#ifndef __XML_FILE_H__
#define __XML_FILE_H__
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <map>
#include <string>
#include <iostream>
using namespace std;
const int XML_READ = 1;
const int XML_WRITE = 0;
typedef struct _XML_INFO XML_INFO;
typedef struct _XML_INFO* HXML_INFO;
struct _XML_INFO
{
char version[16];
int update;
int scan_speed;
int type;
int device_counts;
int item_counts;
map<string, string> map_item_info;
};
class CLibxml2
{
public:
CLibxml2();
~CLibxml2();
CLibxml2(const char *xml_file_path, bool is_read);
/*!
\fn bool open(const char *xml_file_path, bool is_read)
\brief 打开一个XML文件是以读的方式还是以写的方式
\param in xml_file_path XML文件路径
\param in is_read true为读,false为写
\return true成功,false失败
*/
bool open(const char *xml_file_path, bool is_read);
/*!
\fn bool parse_xml_file(XML_INFO &xml_info)
\brief 解析XML文件,将解析后的结果保存在XML_INFO结构体中
\param out xml_info 保存解析后的结果
\return true成功,false失败
*/
bool parse_xml_file(const XML_INFO &xml_info);
/*!
\fn bool save_xml_file(const XML_INFO &xml_info)
\brief 写入XML文件
\param in xml_info 需要写入的信息
\return true成功,false失败
*/
bool save_xml_file(XML_INFO &xml_info);
private:
/*!
\fn xmlNodePtr search_node_ptr(const char *sz_expr)
\brief 查找指定节点
\param in sz_expr 节点路径表达式(XPATH)
\return success返回指定节点指针,fail返回NULL
*/
xmlNodePtr search_node_ptr(const char *sz_expr);
private:
char m_sz_path[512];
xmlDocPtr m_pdoc_read;
xmlNodePtr m_proot;
};
#endif // __XML_FILE_H__
#include "xml-file.h"
#include <string.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/xmlmemory.h>
#include <libxml/xpointer.h>
CLibxml2::CLibxml2()
{
m_pdoc_read = NULL;
m_proot = NULL;
bzero(m_sz_path, sizeof(m_sz_path));
}
CLibxml2::~CLibxml2()
{
if (m_pdoc_read)
{
xmlFreeDoc(m_pdoc_read);
m_pdoc_read = NULL;
xmlCleanupParser();
xmlMemoryDump();
}
}
CLibxml2::CLibxml2(const char *xml_file_path, bool is_read)
{
if (xml_file_path)
{
open(xml_file_path, is_read);
}
}
bool CLibxml2::open(const char *xml_file_path, bool is_read)
{
bool bret = false;
m_pdoc_read = NULL;
m_proot = NULL;
bzero(m_sz_path, sizeof(m_sz_path));
if (xml_file_path)
{
strcpy(m_sz_path, xml_file_path);
if (is_read)
{
xmlKeepBlanksDefault(0);
m_pdoc_read = xmlReadFile(xml_file_path, "UTF-8", XML_PARSE_RECOVER);
m_proot = xmlDocGetRootElement(m_pdoc_read);
}
if (m_proot)
{
bret = true;
}
}
return bret;
}
bool CLibxml2::parse_xml_file(XML_INFO &xml_info)
{
bool bret = false;
if (m_proot)
{
xmlNodePtr node = search_node_ptr("//config_Information");
xmlChar *str = xmlGetProp(node, node->properties->name);
strcpy(xml_info.version, (const char*)BAD_CAST(str));
//cout << xml_info.version << endl;
node = search_node_ptr("//Config_Data_block");
str = xmlGetProp(node, node->properties->name);
xml_info.update = atoi((const char*)BAD_CAST(str));
//cout << xml_info.update << endl;
node = search_node_ptr("//ScanSpeed");
str = xmlNodeGetContent(node);
xml_info.scan_speed = atoi((const char*)BAD_CAST(str));
//cout << xml_info.scan_speed << endl;
node = search_node_ptr("//DeviceType");
str = xmlGetProp(node, node->properties->name);
xml_info.type = atoi((const char*)BAD_CAST(str));
//cout << xml_info.type << endl;
node = search_node_ptr("//Device_Counts");
str = xmlNodeGetContent(node);
xml_info.device_counts = atoi((const char*)BAD_CAST(str));
//cout << xml_info.device_counts << endl;
node = search_node_ptr("//Item_Counts");
str = xmlNodeGetContent(node);
xml_info.item_counts = atoi((const char*)BAD_CAST(str));
//cout << xml_info.item_counts << endl;
int i;
char item_id[32];
char key_word[32];
char id_content[32];
char key_content[32];
xmlNodePtr node_id;
xmlNodePtr node_key;
for (i=1; i<=xml_info.item_counts; i++)
{
bzero(item_id, sizeof(item_id));
bzero(key_word, sizeof(key_word));
bzero(id_content, sizeof(id_content));
bzero(key_content, sizeof(key_content));
sprintf(item_id, "//ItemInfo[%d]/ItemID", i);
sprintf(key_word, "//ItemInfo[%d]/KeyWord", i);
node_id = search_node_ptr(item_id);
node_key = search_node_ptr(key_word);
xmlChar *temp_id = xmlNodeGetContent(node_id);
xmlChar *temp_key = xmlNodeGetContent(node_key);
strcpy(id_content, (const char*)BAD_CAST(temp_id));
strcpy(key_content, (const char*)BAD_CAST(temp_key));
xml_info.map_item_info.insert(pair<string, string>(id_content, key_content));
}
bret = true;
}
return bret;
}
bool CLibxml2::save_xml_file(const XML_INFO &xml_info)
{
if (NULL == m_sz_path)
{
return false;
}
char sz_temp[32];
xmlDocPtr pdoc = xmlNewDoc(BAD_CAST(xml_info.version));
xmlNodePtr config_info = xmlNewNode(NULL, BAD_CAST"config_Information");
xmlNewProp(config_info, BAD_CAST"version", BAD_CAST(xml_info.version));
xmlDocSetRootElement(pdoc, config_info);
xmlNodePtr data_block = xmlNewNode(NULL, BAD_CAST"Config_Data_block");
bzero(sz_temp, sizeof(sz_temp));
sprintf(sz_temp, "%d", xml_info.update);
xmlNewProp(data_block, BAD_CAST"update", BAD_CAST(sz_temp));
xmlAddChild(config_info, data_block);
bzero(sz_temp, sizeof(sz_temp));
sprintf(sz_temp, "%d", xml_info.scan_speed);
xmlNewTextChild(data_block, NULL, BAD_CAST"ScanSpeed", BAD_CAST(sz_temp));
bzero(sz_temp, sizeof(sz_temp));
sprintf(sz_temp, "%d", xml_info.type);
xmlNodePtr device_type = xmlNewNode(NULL, BAD_CAST"DeviceType");
xmlNewProp(device_type, BAD_CAST"type", BAD_CAST(sz_temp));
xmlAddChild(data_block, device_type);
bzero(sz_temp, sizeof(sz_temp));
sprintf(sz_temp, "%d", xml_info.item_counts);
xmlNewTextChild(device_type, NULL, BAD_CAST"Item_Counts", BAD_CAST(sz_temp));
int index = 1;
int ncounts = xml_info.item_counts;
xmlNodePtr item_list = xmlNewNode(NULL, BAD_CAST"Item_list");
xmlAddChild(device_type, item_list);
map<string, string>::iterator iter;
for (iter=xml_info.map_item_info.begin();
iter!=xml_info.map_item_info.end();
++iter)
{
bzero(sz_temp, sizeof(sz_temp));
sprintf(sz_temp, "%d", index++);
xmlNodePtr item_info = xmlNewNode(NULL, BAD_CAST"ItemInfo");
xmlNewProp(item_info, BAD_CAST"NO", BAD_CAST(sz_temp));
xmlAddChild(item_list, item_info);
xmlNewTextChild(item_info, NULL, BAD_CAST"ItemID",
BAD_CAST((*iter).first.c_str()));
xmlNewTextChild(item_info, NULL, BAD_CAST"KeyWord",
BAD_CAST((*iter).second.c_str()));
}
xmlSaveFormatFileEnc(m_sz_path, pdoc, "UTF-8", 1);
xmlFreeDoc(pdoc);
return true;
}
xmlNodePtr CLibxml2::search_node_ptr(const char *sz_expr)
{
xmlNodePtr node_ret;
if (sz_expr == NULL)
{
return NULL;
}
xmlChar *sz_path = BAD_CAST(sz_expr);
xmlXPathContextPtr context = xmlXPathNewContext(m_pdoc_read);
xmlXPathObjectPtr result = xmlXPathEvalExpression(sz_path, context);
if (result == NULL)
{
return NULL;
}
if (xmlXPathNodeSetIsEmpty(result->nodesetval))
{
return NULL;
}
xmlXPathFreeContext(context);
node_ret = xmlXPtrBuildNodeList(result);
return node_ret;
}
/*/测试//
int main(void)
{
//write/
CLibxml2 lib("rmc1.xml", XML_WRITE);
map<string, string> map_item;
XML_INFO xml_info;
xml_info.map_item_info.insert(pair<string, string>("CPU", ""));
xml_info.map_item_info.insert(pair<string, string>("MEM", ""));
xml_info.map_item_info.insert(pair<string, string>("DISK_C_FREE", "C"));
xml_info.map_item_info.insert(pair<string, string>("RunTime", ""));
xml_info.map_item_info.insert(pair<string, string>("MainProcess0", "test.exe"));
xml_info.map_item_info.insert(pair<string, string>("NetPing", "127.0.0.1"));
strcpy(xml_info.version, "1.0");
xml_info.update = 0;
xml_info.scan_speed = 100;
xml_info.type = 2;
xml_info.device_counts = 2;
xml_info.item_counts = xml_info.map_item_info.size();
lib.save_xml_file(xml_info);
//
//read/
XML_INFO xml_info;
CLibxml2 lib("rmc.xml", XML_READ);
lib.parse_xml_file(xml_info);
map<string, string>::iterator iter;
for (iter = xml_info.map_item_info.begin();
iter != xml_info.map_item_info.end();
++iter)
{
cout << (*iter).first << endl;
cout << (*iter).second << endl;
}
return 0;
}
//*
<?xml version="1.0"?>
<config_Information version="1.0">
<Config_Data_block update="0">
<ScanSpeed>100</ScanSpeed>
<DeviceType type="2">
<Device_Counts>1</Device_Counts>
<Item_Counts>6</Item_Counts>
<Item_list>
<ItemInfo NO="1">
<ItemEvenFlag>1</ItemEvenFlag>
<ItemID>CPU</ItemID>
<KeyWord></KeyWord>
</ItemInfo>
<ItemInfo NO="2">
<ItemID>MEM</ItemID>
<KeyWord></KeyWord>
</ItemInfo>
<ItemInfo NO="3">
<ItemID>DISK_C_FREE</ItemID>
<KeyWord>C</KeyWord>
</ItemInfo>
<ItemInfo NO="4">
<ItemID>RunTime</ItemID>
<KeyWord></KeyWord>
</ItemInfo>
<ItemInfo NO="5">
<ItemID>MainProcess0</ItemID>
<KeyWord>test.exe</KeyWord>
</ItemInfo>
<ItemInfo NO="6">
<ItemID>NetPing</ItemID>
<KeyWord>127.0.0.1</KeyWord>
</ItemInfo>
</Item_list>
</DeviceType>
</Config_Data_block>
</config_Information>
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献4条内容
所有评论(0)