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'\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库并添加到项目中,代码才能正常运行。

你可能感兴趣的:(boost)