下面是本人使用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'\t', 1, L"utf-8"); 72 #else 73 std::locale current_locale; 74 boost::property_tree::xml_parser::xml_writer_settings<char> settings('\t', 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.\nPlease 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.\nPlease 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库并添加到项目中,代码才能正常运行。