boost::xml——基本操作以及中文乱码解决方案

下面是本人使用boost库的xml部分的基础操作,并且解决对于大家使用boost库读写中文xml内容出现的乱码问题。

1.实现boost库xml基本操作
2.解决boost对xml中中文乱码问题
3.实现普通字符串和宽字符串的傻瓜切换(模仿tchar.h)
4.代码运行环境为VS2010,需要导入boost库才能正常运行
5.VS2010运行时可能会发生错误。例如:cl.exe 或者 cvtres.exe 报错。 解决办法就是重新打开项目或者切换其它正常项目运行一下(反正我是这么解决的)

下面是源码部分。

注:为了说明问题使用一个cpp文件完成所有操作。

  1 /*实现单字节和宽字节的自动转换*/
  2 
  3 //note_1: G prefix is global meaning
  4 //note_2: template<typename type> ,type only support tstring, can't support int and so on.
  5 //note_3: In VS2010 update1, it maybe encounter bug for VS2010 self. example: "error MSB6006: CL.exe" or "LINK : fatal error LNK1158: cvtres.exe", solution is reopen project
  6 //note_4: switch std::string and std::wstring in use macro CHINESE_CHARSET. The major solution is chinese unreadable code with xml file
  7 
  8 //Windows API
  9 //#include <tchar.h>
 10 //#include <wchar.h>
 11 
 12 //C++ standard template library
 13 #include <iostream>
 14 #include <string>
 15 #include <exception>
 16 #include <map>
 17 
 18 //third library head files
 19 #include <boost/property_tree/ptree.hpp>
 20 #include <boost/property_tree/xml_parser.hpp>
 21 #include <boost/program_options/detail/convert.hpp>
 22 #include <boost/program_options/detail/utf8_codecvt_facet.hpp>
 23 #include <boost/foreach.hpp>
 24 
 25 using namespace std;
 26 using namespace boost;
 27 using namespace boost::property_tree;
 28 
 29 
 30 #define CHINESE_CHARSET //控制处理宽字符还是单字节字符,其中宽字符可以对中文进行支持
 31 
 32 #ifdef CHINESE_CHARSET
 33 #define tptree boost::property_tree::wptree
 34 #define tstring std::wstring
 35 #define _USERT(x) L ## x
 36 #else
 37 #define tptree boost::property_tree::ptree
 38 #define tstring std::string
 39 #define _USERT(x) x
 40 #endif
 41 
 42 bool LoadXML(tptree &o_pt, const string i_strFileName)
 43 {
 44     //set locale
 45 #ifdef CHINESE_CHARSET
 46     std::locale current_locale(locale(""), new boost::program_options::detail::utf8_codecvt_facet());
 47 #else
 48     std::locale current_locale;
 49 #endif
 50 
 51     //read xml
 52     try
 53     {
 54         boost::property_tree::read_xml(i_strFileName, o_pt, boost::property_tree::xml_parser::trim_whitespace, current_locale);
 55     }
 56     catch (const std::exception &e)
 57     {
 58         cout << "Error:" << typeid(e).name() << ": ";
 59         cout << e.what() << endl;
 60         return false;
 61     }
 62     
 63     return true;
 64 }
 65 
 66 bool SaveXML(const tptree &i_pt, const string i_strFileName)
 67 {
 68     //set locale
 69 #ifdef CHINESE_CHARSET
 70     std::locale current_locale(locale(""), new boost::program_options::detail::utf8_codecvt_facet());
 71     boost::property_tree::xml_parser::xml_writer_settings<wchar_t> settings(L'	', 1, L"utf-8");
 72 #else
 73     std::locale current_locale;
 74     boost::property_tree::xml_parser::xml_writer_settings<char> settings('	', 1, "utf-8");
 75 #endif
 76 
 77     try
 78     {
 79         boost::property_tree::write_xml(i_strFileName, i_pt, current_locale, settings);
 80     }
 81     catch (const std::exception &e)
 82     {
 83         cout << "Error:" << typeid(e).name() << ": ";
 84         cout << e.what() << endl;
 85         return false;
 86     }
 87 
 88     return true;
 89 }
 90 
 91 //是否存在直接子节点或者属性,返回-1:出现错误;返回0:没有子节点或者属性;返回1:有属性或者有子节点
 92 int IsExistChildNode(const tptree &i_pt, const tstring i_strNodePath)
 93 {
 94     try
 95     {
 96         const tptree pt = i_pt.get_child(i_strNodePath);
 97         if (pt.empty())
 98         {
 99             return 0; //no child
100         }
101         else
102         {
103             return 1; //have child or attribute
104         }
105     }
106     catch (const std::exception &e)
107     {
108         cout << "Error:" << typeid(e).name() << ": ";
109         cout << e.what() << endl;
110         return -1; //error: exception
111     }
112 
113     return -1;
114 }
115 
116 //查看是否有子节点或者属性,如果没有则返回false,如果有则返回true
117 //通过o_nChildNodeCount和o_nChildNodeAttributeCount返回数目
118 //通过o_bChildNodeOrAttribute判断是直接子节点还是属性:true直接子节点;false属性
119 bool IsChildNodeOrAttr(const tptree &i_pt
120     , const tstring i_strNodePath
121     , bool &o_bChildNodeOrAttribute
122     , int &o_nChildNodeCount //直接子节点数目
123     , int &o_nChildNodeAttributeCount) //直接子节点属性数目
124 {
125     o_bChildNodeOrAttribute = false; //initialize
126     o_nChildNodeCount = 0; //initialize child node count
127     o_nChildNodeAttributeCount = 0; //initialize attribute count
128 
129     tstring l_strChildNode; //local object
130     tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode
131     tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr>
132     bool l_bflag = true; //valve
133 
134     try
135     {
136         int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath);
137         if (0==l_bExistChildNode)
138         {
139             return false; //no child node or attribute
140         }
141         BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath))
142         {
143             l_strChildNode = v.first.data();
144             if (l_strChildNode==l_strXmlAttr && true==l_bflag)
145             {
146                 BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath+l_strAttrPath))
147                 {
148                     ++o_nChildNodeAttributeCount;
149                     o_bChildNodeOrAttribute = false; //is attribute
150                 }
151                 l_bflag = false;
152             }
153             else
154             {
155                 ++o_nChildNodeCount;
156                 o_bChildNodeOrAttribute = true; //is child node
157             }
158         }
159         return true;
160     }
161     catch (const std::exception &e)
162     {
163         cout << "Error:" << typeid(e).name() << ": ";
164         cout << e.what() << endl;
165         return false; //error: exception
166     }
167 
168     return false;
169 }
170 
171 //返回获取直接子节点是否完成:false:获取失败;true:获取成功
172 //获取的直接子节点保存在o_mapChildNode容器中
173 //注意:使用前请先确认是否有直接子节点,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute
174 template<typename type> bool GetChildNodes(const tptree &i_pt, const tstring i_strNodePath, multimap<tstring, type> &o_mmapChildNodes)
175 {
176     tstring l_strChildNode;
177     tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode
178     type l_tpChildNodeValue;
179 
180     try
181     {
182         int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath);
183         if (0==l_bExistChildNode)
184         {
185             return false; //no child node or attribute
186         }
187         BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath))
188         {
189             l_strChildNode = v.first.data();
190             l_tpChildNodeValue = v.second.get_value<type>();
191             if (0!=l_strChildNode.compare(l_strXmlAttr))
192             {
193                 o_mmapChildNodes.insert(pair<tstring, type>(l_strChildNode, l_tpChildNodeValue));
194             }
195             else
196             {
197                 throw runtime_error("This node include with attribute.
Please call IsChildNodeOrAttr function before.");
198             }
199         }
200     }
201     catch (const std::exception &e)
202     {
203         cout << "Error:" << typeid(e).name() << ": ";
204         cout << e.what() << endl;
205         return false; //error: exception
206     }
207 
208     return false;
209 }
210 
211 //返回获取当前节点属性是否完成:false:获取失败;true:获取成功
212 //获取的当前节点属性保存在o_mapCurrentNodeAttrs容器中
213 //注意:使用前请先确认当前节点是否有属性,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute
214 template<typename type> bool GetCurrentNodeAttrs(const tptree &i_pt, const tstring i_strNodePath, map<tstring, type> &o_mapCurrentNodeAttrs)
215 {
216     tstring l_strChildNodeAttr;
217     tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode
218     tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr>
219     type l_tpChildNodeAttrValue;
220 
221     try
222     {
223         int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath);
224         if (0==l_bExistChildNode)
225         {
226             return false; //no child node or attribute
227         }
228         if (l_strXmlAttr==i_pt.get_child(i_strNodePath).begin()->first.data())
229         {
230             BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath+l_strAttrPath))
231             {
232                 l_strChildNodeAttr = v.first.data();
233                 l_tpChildNodeAttrValue = v.second.get_value<type>();
234                 o_mapCurrentNodeAttrs.insert(pair<tstring, type>(l_strChildNodeAttr, l_tpChildNodeAttrValue));
235             }
236             return true;
237         }
238         else
239         {
240             throw runtime_error("This node exclude with attribute.
Please call IsChildNodeOrAttr function before.");
241         }
242     }
243     catch (const std::exception &e)
244     {
245         cout << "Error:" << typeid(e).name() << ": ";
246         cout << e.what() << endl;
247         return false; //error: exception
248     }
249 
250     return false;
251 }
252 
253 //返回获取当前节点的直接子节点属性是否完成:false:获取失败;true:获取成功
254 //获取的当前节点的直接子节点属性保存在o_mapChildNodesAttr容器中
255 //注意:使用前请先确认当前节点的直接子节点是否有属性,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute
256 //注意:本功能只应用在当前节点的多个直接子节点具有相同节点名的情况,对于多个直接子节点具有不同节点名情况不适用
257 template<typename type> bool GetChildNodesAttrs(const tptree &i_pt, const tstring i_strNodePath, multimap<tstring, map<tstring, type>> &o_mmapChildNodesAttrs)
258 {
259     tstring l_strChildNode;
260     tstring l_strChildNodeAttr;
261     type l_tpChildNodeAttrValue;
262     tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode
263     tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr>
264 
265     try
266     {
267         int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath); //check child node
268         if (0==l_bExistChildNode)
269         {
270             return false; //no child node
271         }
272 
273         //tstring l_strChildNode = i_pt.get_child(i_strNodePath).begin()->first.data();
274         tstring l_strChildNode = i_pt.get_child(i_strNodePath).front().first.data();
275         tstring l_strChildNodeAttrPath = i_strNodePath+_USERT(".")+l_strChildNode+l_strAttrPath;
276         int l_bExistChildNodeAttr = IsExistChildNode(i_pt, l_strChildNodeAttrPath); //check child node attribute
277         if (0==l_bExistChildNodeAttr)
278         {
279             return false; //no child node attribute
280         }
281 
282         BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath))
283         {
284             map<tstring, type> l_mapChildNodeAttrs;
285             l_strChildNode = v.first.data();
286             BOOST_FOREACH (const tptree::value_type &subv, v.second.get_child(l_strXmlAttr))
287             {
288                 l_strChildNodeAttr = subv.first.data();
289                 l_tpChildNodeAttrValue = subv.second.get_value<type>();
290                 l_mapChildNodeAttrs.insert(pair<tstring, type>(l_strChildNodeAttr, l_tpChildNodeAttrValue));
291             }
292             o_mmapChildNodesAttrs.insert(pair<tstring, map<tstring, type>>(l_strChildNode, l_mapChildNodeAttrs));
293         }
294         return true;
295     }
296     catch (const std::exception &e)
297     {
298         cout << "Error:" << typeid(e).name() << ": ";
299         cout << e.what() << endl;
300         return false; //error: exception
301     }
302 
303     return false;
304 }
305 
306 //提供指向指定节点的可读写迭代器io_iter,使用i_strNodeValue修改指定节点的值
307 bool SetCurrentNodeValue(tptree::iterator io_iter, const tstring i_strNodeValue)
308 {
309     try
310     {
311         io_iter->second.put_value<tstring>(i_strNodeValue);
312         return true;
313     }
314     catch (const std::exception &e)
315     {
316         cout << "Error:" << typeid(e).name() << ": ";
317         cout << e.what() << endl;
318         return false; //error: exception
319     }
320 
321     return false;
322 }
323 
324 //提供指向指定节点属性的可读写迭代器io_iter,使用i_strNodeAttrValue修改指定节点的值
325 bool SetCurrentNodeAttrValue(tptree::iterator io_iter, const tstring i_strNodeAttrValue)
326 {
327     try
328     {
329         io_iter->second.put_value<tstring>(i_strNodeAttrValue);
330         return true;
331     }
332     catch (const std::exception &e)
333     {
334         cout << "Error:" << typeid(e).name() << ": ";
335         cout << e.what() << endl;
336         return false; //error: exception
337     }
338 
339     return false;
340 }
341 
342 //提供指向指定节点的迭代器io_iter,将该节点删除
343 //节点io_pt就是迭代器io_iter指定的节点本身
344 //注:也可以删除节点属性,删除属性请使用<xmlattr>
345 bool DelCurrentNode(tptree &io_pt, tptree::iterator i_iter)
346 {
347     try
348     {
349         io_pt.erase(i_iter);
350         return true;
351     }
352     catch (const std::exception &e)
353     {
354         cout << "Error:" << typeid(e).name() << ": ";
355         cout << e.what() << endl;
356         return false; //error: exception
357     }
358 
359     return false;
360 }
361 
362 //当前节点io_pt
363 //将该节点以及所有具有相同节点名字节点删除
364 //注:也可以删除节点属性,删除属性请使用<xmlattr>
365 tptree::size_type DelCurrentNodes(tptree &io_pt, const tstring &i_strChildNode)
366 {
367     try
368     {
369         return io_pt.erase(i_strChildNode);
370     }
371     catch (const std::exception &e)
372     {
373         cout << "Error:" << typeid(e).name() << ": ";
374         cout << e.what() << endl;
375         return -1; //error: exception
376     }
377 
378     return -1;
379 }
380 
381 
382 void main()
383 {
384     //test code
385     string l_strFileName1("F:\Desktop\20140411\测试\testxml.xml");
386     string l_strFileName2("F:\Desktop\20140411\测试\testxml2.xml");
387     tptree pt;
388     bool f = LoadXML(pt, l_strFileName1);
389 
390     //测试IsExistChildNode函数
391     //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>.id"));
392     //int l_nState1 = IsExistChildNode(pt, l_strNodePath);
393 
394     //测试IsExistChildNode函数
395     //tstring l_strNodePath(_USERT("config.departments.department.info.person")); //有直接子节点或者属性
396     //int l_nState2 = IsExistChildNode(pt, l_strNodePath);
397 
398     //测试IsChildNodeOrAttr函数
399     //tstring l_strNodePath(_USERT("config.departments.department.info"));
400     //bool l_bChildNodeOrAttribute;
401     //int l_nChildNodeCount;
402     //int l_nChildNodeAttributeCount;
403     //bool f3 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
404 
405     //测试IsChildNodeOrAttr函数
406     //tstring l_strNodePath(_USERT("config.departments.department.info.person"));
407     //bool l_bChildNodeOrAttribute;
408     //int l_nChildNodeCount;
409     //int l_nChildNodeAttributeCount;
410     //bool f3 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
411 
412     //测试GetChildNodes函数
413     //tstring l_strNodePath(_USERT("config.departments.department.info"));
414     //bool l_bChildNodeOrAttribute;
415     //int l_nChildNodeCount;
416     //int l_nChildNodeAttributeCount;
417     //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
418     //bool f5;
419     //multimap<tstring, tstring> l_mapChildNodes;
420     //if (l_bChildNodeOrAttribute)
421     //{
422     //    f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes);
423     //}
424 
425     //测试GetChildNodes函数
426     //typ==int error
427     //tstring l_strNodePath(_USERT("config.departments.department.info"));
428     //bool l_bChildNodeOrAttribute;
429     //int l_nChildNodeCount;
430     //int l_nChildNodeAttributeCount;
431     //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
432     //bool f5;
433     //multimap<tstring, int> l_mapChildNodes;
434     //if (l_bChildNodeOrAttribute)
435     //{
436     //    f5 = GetChildNodes<int>(pt, l_strNodePath, l_mapChildNodes);
437     //}
438 
439     //测试GetChildNodes函数
440     //tstring l_strNodePath(_USERT("config.departments.department"));
441     //bool l_bChildNodeOrAttribute;
442     //int l_nChildNodeCount;
443     //int l_nChildNodeAttributeCount;
444     //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
445     //bool f5;
446     //multimap<tstring, tstring> l_mapChildNodes;
447     //if (l_bChildNodeOrAttribute)
448     //{
449     //    f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes);
450     //}
451 
452     //测试GetCurrentNodeAttrs函数
453     //tstring l_strNodePath(_USERT("config.departments.department.info.person"));
454     //multimap<tstring, tstring> l_mapChildNodes;
455     //bool f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes);
456 
457     //测试GetCurrentNodeAttrs函数
458     //tstring l_strNodePath(_USERT("config.departments.department.info.person"));
459     //bool l_bChildNodeOrAttribute;
460     //int l_nChildNodeCount;
461     //int l_nChildNodeAttributeCount;
462     //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount);
463     //bool f5;
464     //map<tstring, tstring> l_mapChildNodeAttrs;
465     //if (!l_bChildNodeOrAttribute)
466     //{
467     //    f5 = GetCurrentNodeAttrs<tstring>(pt, l_strNodePath, l_mapChildNodeAttrs);
468     //}
469 
470     //测试GetChildNodesAttrs函数
471     //tstring l_strNodePath(_USERT("config.departments.department.info"));
472     //bool f5;
473     ////map<tstring, tstring> l_mapChildNodeAttrs;
474     //multimap<tstring, map<tstring, tstring>> l_mmapChildNodesAttrs;
475     //f5 = GetChildNodesAttrs<tstring>(pt, l_strNodePath, l_mmapChildNodesAttrs);
476 
477     //测试SetCurrentNodeValue函数
478     //tstring l_strNodePath(_USERT("config.departments.department.info"));
479     //tptree::iterator iter= pt.get_child(l_strNodePath).begin();
480     //tstring l_strNodeValue = _USERT("testvalue");
481     //bool f6 = SetCurrentNodeValue(iter, l_strNodeValue);
482 
483     //测试SetCurrentNodeAttrValue函数
484     //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>"));
485     //tptree::iterator iter= pt.get_child(l_strNodePath).begin();
486     //tstring l_strNodeValue = _USERT("testvalue");
487     //bool f6 = SetCurrentNodeAttrValue(iter, l_strNodeValue);
488 
489     //测试DelCurrentNode函数
490     //tstring l_strNodePath(_USERT("config.departments.department.info"));
491     //tptree &childpt = pt.get_child(l_strNodePath);
492     //tptree::iterator iter = childpt.begin();
493     //bool f6 = DelCurrentNode(childpt, ++iter);
494     
495     //测试DelCurrentNode函数
496     //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>"));
497     //tptree &childpt = pt.get_child(l_strNodePath);
498     //tptree::iterator iter = childpt.begin();
499     //bool f6 = DelCurrentNode(childpt, ++iter);
500 
501     //测试DelCurrentNodes函数
502     //tstring l_strNodePath(_USERT("config.departments.department.info"));
503     //tptree &childpt = pt.get_child(l_strNodePath);
504     //tptree::key_type kt = childpt.begin()->first;
505     //tptree::size_type st6 = DelCurrentNodes(childpt, kt);
506 
507     //测试DelCurrentNodes函数
508     //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>"));
509     //tptree &childpt = pt.get_child(l_strNodePath);
510     //tptree::key_type kt = childpt.begin()->first;
511     //tptree::size_type st6 = DelCurrentNodes(childpt, kt);
512 
513     //bool f2 = SaveXML(pt, l_strFileName2);
514 
515     cout << endl;
516 }

 testxml.xml测试文件:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <config>
 3   <mainformsize height="600" width="330" top="50" left="500"/>
 4   <applicationtitle>GoCom统一通讯应用平台</applicationtitle>
 5   <loginmark>
 6       <fontsize>14</fontsize>
 7       <fontcolor>$0000ff</fontcolor>
 8       <lantern>true</lantern>
 9       <clientversion>5.3.5.17</clientversion>
10       <serverip>imbs1.smartdot.com.cn</serverip>
11   </loginmark>
12   <departments>
13       <department>
14           <name>donghe</name>
15           <level>2</level>
16           <personcount>3</personcount>
17           <info>
18               <person id="1_1_1" name="王慧敏"/>
19               <person id="1_1_2" name="刘东升"/>
20               <person id="1_1_3" name="张智卓"/>
21           </info>
22       </department>
23       <department>
24           <name>boyun</name>
25           <level>2</level>
26           <personcount>3</personcount>
27           <info>
28               <person id="1_2_1" name="朗朗"/>
29               <person id="1_2_2" name="隋国龙"/>
30           </info>
31       </department>
32   </departments>
33 </config>

注:代码可以正常运行在VS2010环境下,先下载安装boost库并添加到项目中,代码才能正常运行。

煮酒论英雄
原文地址:https://www.cnblogs.com/superstargg/p/3704755.html