C++读写XML文件(libxml2库)

C++程序有时候要读写XML文件, 这里介绍一个读写XML文件的库——Libxml2。

主页:http://xmlsoft.org/index.html

入门教程很详细的:http://jianlee.ylinux.org/Computer/C/libxml.html#sec11

读取节点内容的话用XPath方式比较好,要问XPath与Libxml2库之间的关系,有个很形象的比喻:

那就是SQL与数据库之间的关系。


下面的代码是在Linux下实现的:

  1. #ifndef __XML_FILE_H__  
  2. #define __XML_FILE_H__  
  3.   
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6. #include <libxml/parser.h>  
  7. #include <libxml/tree.h>  
  8. #include <map>  
  9. #include <string>  
  10. #include <iostream>  
  11.   
  12. using namespace std;  
  13.   
  14. const int XML_READ = 1;  
  15. const int XML_WRITE = 0;  
  16.   
  17. typedef struct _XML_INFO XML_INFO;  
  18. typedef struct _XML_INFO* HXML_INFO;  
  19.   
  20. struct _XML_INFO  
  21. {  
  22.     char version[16];  
  23.     int update;  
  24.     int scan_speed;  
  25.     int type;  
  26.     int device_counts;  
  27.     int item_counts;  
  28.       
  29.     map<string, string> map_item_info;  
  30. };  
  31.   
  32. class CLibxml2  
  33. {  
  34. public:  
  35.     CLibxml2();  
  36.     ~CLibxml2();  
  37.   
  38.     CLibxml2(const char *xml_file_path, bool is_read);  
  39.   
  40.     /*! 
  41.       \fn bool open(const char *xml_file_path, bool is_read) 
  42.       \brief 打开一个XML文件是以读的方式还是以写的方式 
  43.       \param in xml_file_path XML文件路径 
  44.       \param in is_read true为读,false为写 
  45.       \return true成功,false失败 
  46.     */  
  47.     bool open(const char *xml_file_path, bool is_read);  
  48.       
  49.     /*! 
  50.       \fn bool parse_xml_file(XML_INFO &xml_info) 
  51.       \brief 解析XML文件,将解析后的结果保存在XML_INFO结构体中 
  52.       \param out xml_info 保存解析后的结果 
  53.       \return true成功,false失败 
  54.     */  
  55.     bool parse_xml_file(const XML_INFO &xml_info);  
  56.   
  57.     /*! 
  58.       \fn bool save_xml_file(const XML_INFO &xml_info) 
  59.       \brief 写入XML文件 
  60.       \param in xml_info 需要写入的信息 
  61.       \return true成功,false失败 
  62.     */  
  63.     bool save_xml_file(XML_INFO &xml_info);  
  64.   
  65. private:  
  66.     /*! 
  67.       \fn xmlNodePtr search_node_ptr(const char *sz_expr) 
  68.       \brief 查找指定节点 
  69.       \param in sz_expr 节点路径表达式(XPATH) 
  70.       \return success返回指定节点指针,fail返回NULL 
  71.     */  
  72.     xmlNodePtr search_node_ptr(const char *sz_expr);  
  73.   
  74. private:  
  75.     char m_sz_path[512];  
  76.     xmlDocPtr m_pdoc_read;  
  77.     xmlNodePtr m_proot;  
  78. };  
  79.   
  80.   
  81. #endif // __XML_FILE_H__  

 

  1. #include "xml-file.h"  
  2. #include <string.h>  
  3. #include <libxml/xpath.h>  
  4. #include <libxml/xpathInternals.h>  
  5. #include <libxml/xmlmemory.h>  
  6. #include <libxml/xpointer.h>  
  7.   
  8. CLibxml2::CLibxml2()  
  9. {  
  10.     m_pdoc_read = NULL;  
  11.     m_proot = NULL;  
  12.     bzero(m_sz_path, sizeof(m_sz_path));  
  13. }  
  14.   
  15. CLibxml2::~CLibxml2()  
  16. {  
  17.     if (m_pdoc_read)  
  18.     {  
  19.         xmlFreeDoc(m_pdoc_read);  
  20.         m_pdoc_read = NULL;  
  21.   
  22.         xmlCleanupParser();  
  23.         xmlMemoryDump();  
  24.     }  
  25. }  
  26.   
  27. CLibxml2::CLibxml2(const char *xml_file_path, bool is_read)  
  28. {  
  29.     if (xml_file_path)  
  30.     {  
  31.         open(xml_file_path, is_read);  
  32.     }  
  33. }  
  34.   
  35. bool CLibxml2::open(const char *xml_file_path, bool is_read)  
  36. {  
  37.     bool bret = false;  
  38.       
  39.     m_pdoc_read = NULL;  
  40.     m_proot = NULL;  
  41.     bzero(m_sz_path, sizeof(m_sz_path));  
  42.       
  43.     if (xml_file_path)  
  44.     {  
  45.         strcpy(m_sz_path, xml_file_path);  
  46.   
  47.         if (is_read)  
  48.         {  
  49.             xmlKeepBlanksDefault(0);  
  50.             m_pdoc_read = xmlReadFile(xml_file_path, "UTF-8", XML_PARSE_RECOVER);  
  51.             m_proot = xmlDocGetRootElement(m_pdoc_read);  
  52.         }  
  53.           
  54.         if (m_proot)  
  55.         {  
  56.             bret = true;  
  57.         }  
  58.     }  
  59.   
  60.     return bret;  
  61. }  
  62.   
  63. bool CLibxml2::parse_xml_file(XML_INFO &xml_info)  
  64. {  
  65.     bool bret = false;  
  66.     if (m_proot)  
  67.     {  
  68.         xmlNodePtr node = search_node_ptr("//config_Information");  
  69.         xmlChar *str = xmlGetProp(node, node->properties->name);  
  70.         strcpy(xml_info.version, (const char*)BAD_CAST(str));  
  71.         //cout << xml_info.version << endl;  
  72.   
  73.         node = search_node_ptr("//Config_Data_block");  
  74.         str = xmlGetProp(node, node->properties->name);  
  75.         xml_info.update = atoi((const char*)BAD_CAST(str));  
  76.         //cout << xml_info.update << endl;  
  77.   
  78.         node = search_node_ptr("//ScanSpeed");  
  79.         str = xmlNodeGetContent(node);  
  80.         xml_info.scan_speed = atoi((const char*)BAD_CAST(str));  
  81.         //cout << xml_info.scan_speed << endl;  
  82.   
  83.         node = search_node_ptr("//DeviceType");  
  84.         str = xmlGetProp(node, node->properties->name);  
  85.         xml_info.type = atoi((const char*)BAD_CAST(str));  
  86.         //cout << xml_info.type << endl;  
  87.   
  88.         node = search_node_ptr("//Device_Counts");  
  89.         str = xmlNodeGetContent(node);  
  90.         xml_info.device_counts = atoi((const char*)BAD_CAST(str));  
  91.         //cout << xml_info.device_counts << endl;  
  92.   
  93.         node = search_node_ptr("//Item_Counts");  
  94.         str = xmlNodeGetContent(node);  
  95.         xml_info.item_counts = atoi((const char*)BAD_CAST(str));  
  96.         //cout << xml_info.item_counts << endl;  
  97.   
  98.         int i;  
  99.         char item_id[32];  
  100.         char key_word[32];  
  101.         char id_content[32];  
  102.         char key_content[32];  
  103.         xmlNodePtr node_id;  
  104.         xmlNodePtr node_key;  
  105.           
  106.         for (i=1; i<=xml_info.item_counts; i++)  
  107.         {  
  108.             bzero(item_id, sizeof(item_id));  
  109.             bzero(key_word, sizeof(key_word));  
  110.             bzero(id_content, sizeof(id_content));  
  111.             bzero(key_content, sizeof(key_content));  
  112.               
  113.             sprintf(item_id, "//ItemInfo[%d]/ItemID", i);  
  114.             sprintf(key_word, "//ItemInfo[%d]/KeyWord", i);  
  115.             node_id = search_node_ptr(item_id);  
  116.             node_key = search_node_ptr(key_word);  
  117.             xmlChar *temp_id = xmlNodeGetContent(node_id);  
  118.             xmlChar *temp_key = xmlNodeGetContent(node_key);  
  119.             strcpy(id_content, (const char*)BAD_CAST(temp_id));  
  120.             strcpy(key_content, (const char*)BAD_CAST(temp_key));  
  121.             xml_info.map_item_info.insert(pair<string, string>(id_content, key_content));  
  122.         }  
  123.           
  124.         bret = true;  
  125.     }  
  126.   
  127.     return bret;  
  128. }  
  129.   
  130. bool CLibxml2::save_xml_file(const XML_INFO &xml_info)  
  131. {  
  132.     if (NULL == m_sz_path)  
  133.     {  
  134.         return false;  
  135.     }  
  136.   
  137.     char sz_temp[32];  
  138.       
  139.     xmlDocPtr pdoc = xmlNewDoc(BAD_CAST(xml_info.version));  
  140.     xmlNodePtr config_info = xmlNewNode(NULL, BAD_CAST"config_Information");  
  141.     xmlNewProp(config_info, BAD_CAST"version", BAD_CAST(xml_info.version));  
  142.     xmlDocSetRootElement(pdoc, config_info);  
  143.       
  144.     xmlNodePtr data_block = xmlNewNode(NULL, BAD_CAST"Config_Data_block");  
  145.     bzero(sz_temp, sizeof(sz_temp));  
  146.     sprintf(sz_temp, "%d", xml_info.update);  
  147.     xmlNewProp(data_block, BAD_CAST"update", BAD_CAST(sz_temp));  
  148.     xmlAddChild(config_info, data_block);  
  149.   
  150.     bzero(sz_temp, sizeof(sz_temp));  
  151.     sprintf(sz_temp, "%d", xml_info.scan_speed);  
  152.     xmlNewTextChild(data_block, NULL, BAD_CAST"ScanSpeed", BAD_CAST(sz_temp));  
  153.   
  154.     bzero(sz_temp, sizeof(sz_temp));  
  155.     sprintf(sz_temp, "%d", xml_info.type);  
  156.     xmlNodePtr device_type = xmlNewNode(NULL, BAD_CAST"DeviceType");  
  157.     xmlNewProp(device_type, BAD_CAST"type", BAD_CAST(sz_temp));  
  158.     xmlAddChild(data_block, device_type);  
  159.   
  160.     bzero(sz_temp, sizeof(sz_temp));  
  161.     sprintf(sz_temp, "%d", xml_info.item_counts);  
  162.     xmlNewTextChild(device_type, NULL, BAD_CAST"Item_Counts", BAD_CAST(sz_temp));  
  163.     int index = 1;  
  164.     int ncounts = xml_info.item_counts;  
  165.       
  166.     xmlNodePtr item_list = xmlNewNode(NULL, BAD_CAST"Item_list");  
  167.     xmlAddChild(device_type, item_list);  
  168.   
  169.     map<string, string>::iterator iter;  
  170.     for (iter=xml_info.map_item_info.begin();  
  171.          iter!=xml_info.map_item_info.end();  
  172.          ++iter)  
  173.     {  
  174.           
  175.         bzero(sz_temp, sizeof(sz_temp));  
  176.         sprintf(sz_temp, "%d", index++);  
  177.         xmlNodePtr item_info = xmlNewNode(NULL, BAD_CAST"ItemInfo");  
  178.         xmlNewProp(item_info, BAD_CAST"NO", BAD_CAST(sz_temp));  
  179.         xmlAddChild(item_list, item_info);  
  180.   
  181.         xmlNewTextChild(item_info, NULL, BAD_CAST"ItemID",  
  182.                         BAD_CAST((*iter).first.c_str()));  
  183.         xmlNewTextChild(item_info, NULL, BAD_CAST"KeyWord",  
  184.                         BAD_CAST((*iter).second.c_str()));  
  185.     }  
  186.       
  187.     xmlSaveFormatFileEnc(m_sz_path, pdoc, "UTF-8", 1);  
  188.     xmlFreeDoc(pdoc);  
  189.     return true;  
  190. }  
  191.   
  192. xmlNodePtr CLibxml2::search_node_ptr(const char *sz_expr)  
  193. {  
  194.     xmlNodePtr node_ret;  
  195.       
  196.     if (sz_expr == NULL)  
  197.     {  
  198.         return NULL;  
  199.     }  
  200.       
  201.     xmlChar *sz_path = BAD_CAST(sz_expr);  
  202.     xmlXPathContextPtr context = xmlXPathNewContext(m_pdoc_read);  
  203.     xmlXPathObjectPtr result = xmlXPathEvalExpression(sz_path, context);  
  204.       
  205.     if (result == NULL)  
  206.     {  
  207.         return NULL;  
  208.     }  
  209.     if (xmlXPathNodeSetIsEmpty(result->nodesetval))  
  210.     {  
  211.         return NULL;  
  212.     }  
  213.   
  214.     xmlXPathFreeContext(context);  
  215.       
  216.     node_ret = xmlXPtrBuildNodeList(result);  
  217.   
  218.     return node_ret;  
  219. }  
  220.   
  221. /*/////////测试////////////////////////// 
  222. int main(void) 
  223. { 
  224.     //write///////////////////////////////// 
  225.     CLibxml2 lib("rmc1.xml", XML_WRITE); 
  226.  
  227.     map<string, string> map_item; 
  228.     XML_INFO xml_info; 
  229.     xml_info.map_item_info.insert(pair<string, string>("CPU", "")); 
  230.     xml_info.map_item_info.insert(pair<string, string>("MEM", "")); 
  231.     xml_info.map_item_info.insert(pair<string, string>("DISK_C_FREE", "C")); 
  232.     xml_info.map_item_info.insert(pair<string, string>("RunTime", "")); 
  233.     xml_info.map_item_info.insert(pair<string, string>("MainProcess0", "test.exe")); 
  234.     xml_info.map_item_info.insert(pair<string, string>("NetPing", "127.0.0.1")); 
  235.      
  236.     strcpy(xml_info.version, "1.0"); 
  237.     xml_info.update = 0; 
  238.     xml_info.scan_speed = 100; 
  239.     xml_info.type = 2; 
  240.     xml_info.device_counts = 2; 
  241.     xml_info.item_counts = xml_info.map_item_info.size(); 
  242.  
  243.     lib.save_xml_file(xml_info); 
  244.     ////////////////////////////////////////// 
  245.  
  246.  
  247.     //read///////////////////////////////////// 
  248.     XML_INFO xml_info; 
  249.     CLibxml2 lib("rmc.xml", XML_READ); 
  250.     lib.parse_xml_file(xml_info); 
  251.  
  252.     map<string, string>::iterator iter; 
  253.     for (iter = xml_info.map_item_info.begin(); 
  254.          iter != xml_info.map_item_info.end(); 
  255.          ++iter) 
  256.     { 
  257.         cout << (*iter).first << endl; 
  258.         cout << (*iter).second << endl; 
  259.     } 
  260.     //////////////////////////////////////////// 
  261.  
  262.     
  263.     return 0; 
  264. } 
  265. //*////////////////////////////////  

 

  1. <?xml version="1.0"?>  
  2. <config_Information version="1.0">  
  3. <Config_Data_block update="0">  
  4. <ScanSpeed>100</ScanSpeed>  
  5. <DeviceType type="2">  
  6. <Device_Counts>1</Device_Counts>  
  7. <Item_Counts>6</Item_Counts>  
  8. <Item_list>  
  9. <ItemInfo NO="1">  
  10.     <ItemEvenFlag>1</ItemEvenFlag>  
  11.     <ItemID>CPU</ItemID>  
  12.     <KeyWord></KeyWord>  
  13. </ItemInfo>  
  14. <ItemInfo NO="2">  
  15.     <ItemID>MEM</ItemID>  
  16.     <KeyWord></KeyWord>  
  17. </ItemInfo>  
  18. <ItemInfo NO="3">  
  19.     <ItemID>DISK_C_FREE</ItemID>  
  20.     <KeyWord>C</KeyWord>  
  21. </ItemInfo>  
  22. <ItemInfo NO="4">  
  23.     <ItemID>RunTime</ItemID>  
  24.     <KeyWord></KeyWord>  
  25. </ItemInfo>  
  26. <ItemInfo NO="5">  
  27.     <ItemID>MainProcess0</ItemID>  
  28.     <KeyWord>test.exe</KeyWord>  
  29. </ItemInfo>  
  30. <ItemInfo NO="6">  
  31.     <ItemID>NetPing</ItemID>  
  32.     <KeyWord>127.0.0.1</KeyWord>  
  33. </ItemInfo>  
  34. </Item_list>  
  35. </DeviceType>  
  36. </Config_Data_block>  
  37. </config_Information> 

 

posted on 2013-10-17 11:31  云编程的梦  阅读(4980)  评论(2编辑  收藏  举报

导航