boost::xml——基本操作以及中文乱码解决方案
2014-05-03 02:14
405 查看
下面是本人使用boost库的xml部分的基础操作,并且解决对于大家使用boost库读写中文xml内容出现的乱码问题。
1.实现boost库xml基本操作
2.解决boost对xml中中文乱码问题
3.实现普通字符串和宽字符串的傻瓜切换(模仿tchar.h)
4.代码运行环境为VS2010,需要导入boost库才能正常运行
5.VS2010运行时可能会发生错误。例如:cl.exe 或者 cvtres.exe 报错。 解决办法就是重新打开项目或者切换其它正常项目运行一下(反正我是这么解决的)
下面是源码部分。
注:为了说明问题使用一个cpp文件完成所有操作。
testxml.xml测试文件:
注:代码可以正常运行在VS2010环境下,先下载安装boost库并添加到项目中,代码才能正常运行。
1.实现boost库xml基本操作
2.解决boost对xml中中文乱码问题
3.实现普通字符串和宽字符串的傻瓜切换(模仿tchar.h)
4.代码运行环境为VS2010,需要导入boost库才能正常运行
5.VS2010运行时可能会发生错误。例如:cl.exe 或者 cvtres.exe 报错。 解决办法就是重新打开项目或者切换其它正常项目运行一下(反正我是这么解决的)
下面是源码部分。
注:为了说明问题使用一个cpp文件完成所有操作。
/*实现单字节和宽字节的自动转换*/ //note_1: G prefix is global meaning //note_2: template<typename type> ,type only support tstring, can't support int and so on. //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 //note_4: switch std::string and std::wstring in use macro CHINESE_CHARSET. The major solution is chinese unreadable code with xml file //Windows API //#include <tchar.h> //#include <wchar.h> //C++ standard template library #include <iostream> #include <string> #include <exception> #include <map> //third library head files #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/program_options/detail/convert.hpp> #include <boost/program_options/detail/utf8_codecvt_facet.hpp> #include <boost/foreach.hpp> using namespace std; using namespace boost; using namespace boost::property_tree; #define CHINESE_CHARSET //控制处理宽字符还是单字节字符,其中宽字符可以对中文进行支持 #ifdef CHINESE_CHARSET #define tptree boost::property_tree::wptree #define tstring std::wstring #define _USERT(x) L ## x #else #define tptree boost::property_tree::ptree #define tstring std::string #define _USERT(x) x #endif bool LoadXML(tptree &o_pt, const string i_strFileName) { //set locale #ifdef CHINESE_CHARSET std::locale current_locale(locale(""), new boost::program_options::detail::utf8_codecvt_facet()); #else std::locale current_locale; #endif //read xml try { boost::property_tree::read_xml(i_strFileName, o_pt, boost::property_tree::xml_parser::trim_whitespace, current_locale); } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; } return true; } bool SaveXML(const tptree &i_pt, const string i_strFileName) { //set locale #ifdef CHINESE_CHARSET std::locale current_locale(locale(""), new boost::program_options::detail::utf8_codecvt_facet()); boost::property_tree::xml_parser::xml_writer_settings<wchar_t> settings(L'\t', 1, L"utf-8"); #else std::locale current_locale; boost::property_tree::xml_parser::xml_writer_settings<char> settings('\t', 1, "utf-8"); #endif try { boost::property_tree::write_xml(i_strFileName, i_pt, current_locale, settings); } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; } return true; } //是否存在直接子节点或者属性,返回-1:出现错误;返回0:没有子节点或者属性;返回1:有属性或者有子节点 int IsExistChildNode(const tptree &i_pt, const tstring i_strNodePath) { try { const tptree pt = i_pt.get_child(i_strNodePath); if (pt.empty()) { return 0; //no child } else { return 1; //have child or attribute } } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return -1; //error: exception } return -1; } //查看是否有子节点或者属性,如果没有则返回false,如果有则返回true //通过o_nChildNodeCount和o_nChildNodeAttributeCount返回数目 //通过o_bChildNodeOrAttribute判断是直接子节点还是属性:true直接子节点;false属性 bool IsChildNodeOrAttr(const tptree &i_pt , const tstring i_strNodePath , bool &o_bChildNodeOrAttribute , int &o_nChildNodeCount //直接子节点数目 , int &o_nChildNodeAttributeCount) //直接子节点属性数目 { o_bChildNodeOrAttribute = false; //initialize o_nChildNodeCount = 0; //initialize child node count o_nChildNodeAttributeCount = 0; //initialize attribute count tstring l_strChildNode; //local object tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr> bool l_bflag = true; //valve try { int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath); if (0==l_bExistChildNode) { return false; //no child node or attribute } BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath)) { l_strChildNode = v.first.data(); if (l_strChildNode==l_strXmlAttr && true==l_bflag) { BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath+l_strAttrPath)) { ++o_nChildNodeAttributeCount; o_bChildNodeOrAttribute = false; //is attribute } l_bflag = false; } else { ++o_nChildNodeCount; o_bChildNodeOrAttribute = true; //is child node } } return true; } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //返回获取直接子节点是否完成:false:获取失败;true:获取成功 //获取的直接子节点保存在o_mapChildNode容器中 //注意:使用前请先确认是否有直接子节点,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute template<typename type> bool GetChildNodes(const tptree &i_pt, const tstring i_strNodePath, multimap<tstring, type> &o_mmapChildNodes) { tstring l_strChildNode; tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode type l_tpChildNodeValue; try { int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath); if (0==l_bExistChildNode) { return false; //no child node or attribute } BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath)) { l_strChildNode = v.first.data(); l_tpChildNodeValue = v.second.get_value<type>(); if (0!=l_strChildNode.compare(l_strXmlAttr)) { o_mmapChildNodes.insert(pair<tstring, type>(l_strChildNode, l_tpChildNodeValue)); } else { throw runtime_error("This node include with attribute.\nPlease call IsChildNodeOrAttr function before."); } } } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //返回获取当前节点属性是否完成:false:获取失败;true:获取成功 //获取的当前节点属性保存在o_mapCurrentNodeAttrs容器中 //注意:使用前请先确认当前节点是否有属性,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute template<typename type> bool GetCurrentNodeAttrs(const tptree &i_pt, const tstring i_strNodePath, map<tstring, type> &o_mapCurrentNodeAttrs) { tstring l_strChildNodeAttr; tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr> type l_tpChildNodeAttrValue; try { int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath); if (0==l_bExistChildNode) { return false; //no child node or attribute } if (l_strXmlAttr==i_pt.get_child(i_strNodePath).begin()->first.data()) { BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath+l_strAttrPath)) { l_strChildNodeAttr = v.first.data(); l_tpChildNodeAttrValue = v.second.get_value<type>(); o_mapCurrentNodeAttrs.insert(pair<tstring, type>(l_strChildNodeAttr, l_tpChildNodeAttrValue)); } return true; } else { throw runtime_error("This node exclude with attribute.\nPlease call IsChildNodeOrAttr function before."); } } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //返回获取当前节点的直接子节点属性是否完成:false:获取失败;true:获取成功 //获取的当前节点的直接子节点属性保存在o_mapChildNodesAttr容器中 //注意:使用前请先确认当前节点的直接子节点是否有属性,可以调用IsChildNodeOrAttr查看o_bChildNodeOrAttribute //注意:本功能只应用在当前节点的多个直接子节点具有相同节点名的情况,对于多个直接子节点具有不同节点名情况不适用 template<typename type> bool GetChildNodesAttrs(const tptree &i_pt, const tstring i_strNodePath, multimap<tstring, map<tstring, type>> &o_mmapChildNodesAttrs) { tstring l_strChildNode; tstring l_strChildNodeAttr; type l_tpChildNodeAttrValue; tstring l_strXmlAttr(_USERT("<xmlattr>")); //with l_strChildNode tstring l_strAttrPath(_USERT(".<xmlattr>")); //mark <xmlattr> try { int l_bExistChildNode = IsExistChildNode(i_pt, i_strNodePath); //check child node if (0==l_bExistChildNode) { return false; //no child node } //tstring l_strChildNode = i_pt.get_child(i_strNodePath).begin()->first.data(); tstring l_strChildNode = i_pt.get_child(i_strNodePath).front().first.data(); tstring l_strChildNodeAttrPath = i_strNodePath+_USERT(".")+l_strChildNode+l_strAttrPath; int l_bExistChildNodeAttr = IsExistChildNode(i_pt, l_strChildNodeAttrPath); //check child node attribute if (0==l_bExistChildNodeAttr) { return false; //no child node attribute } BOOST_FOREACH (const tptree::value_type &v, i_pt.get_child(i_strNodePath)) { map<tstring, type> l_mapChildNodeAttrs; l_strChildNode = v.first.data(); BOOST_FOREACH (const tptree::value_type &subv, v.second.get_child(l_strXmlAttr)) { l_strChildNodeAttr = subv.first.data(); l_tpChildNodeAttrValue = subv.second.get_value<type>(); l_mapChildNodeAttrs.insert(pair<tstring, type>(l_strChildNodeAttr, l_tpChildNodeAttrValue)); } o_mmapChildNodesAttrs.insert(pair<tstring, map<tstring, type>>(l_strChildNode, l_mapChildNodeAttrs)); } return true; } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //提供指向指定节点的可读写迭代器io_iter,使用i_strNodeValue修改指定节点的值 bool SetCurrentNodeValue(tptree::iterator io_iter, const tstring i_strNodeValue) { try { io_iter->second.put_value<tstring>(i_strNodeValue); return true; } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //提供指向指定节点属性的可读写迭代器io_iter,使用i_strNodeAttrValue修改指定节点的值 bool SetCurrentNodeAttrValue(tptree::iterator io_iter, const tstring i_strNodeAttrValue) { try { io_iter->second.put_value<tstring>(i_strNodeAttrValue); return true; } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //提供指向指定节点的迭代器io_iter,将该节点删除 //节点io_pt就是迭代器io_iter指定的节点本身 //注:也可以删除节点属性,删除属性请使用<xmlattr> bool DelCurrentNode(tptree &io_pt, tptree::iterator i_iter) { try { io_pt.erase(i_iter); return true; } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return false; //error: exception } return false; } //当前节点io_pt //将该节点以及所有具有相同节点名字节点删除 //注:也可以删除节点属性,删除属性请使用<xmlattr> tptree::size_type DelCurrentNodes(tptree &io_pt, const tstring &i_strChildNode) { try { return io_pt.erase(i_strChildNode); } catch (const std::exception &e) { cout << "Error:" << typeid(e).name() << ": "; cout << e.what() << endl; return -1; //error: exception } return -1; } void main() { //test code string l_strFileName1("F:\\Desktop\\20140411\\测试\\testxml.xml"); string l_strFileName2("F:\\Desktop\\20140411\\测试\\testxml2.xml"); tptree pt; bool f = LoadXML(pt, l_strFileName1); //测试IsExistChildNode函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>.id")); //int l_nState1 = IsExistChildNode(pt, l_strNodePath); //测试IsExistChildNode函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person")); //有直接子节点或者属性 //int l_nState2 = IsExistChildNode(pt, l_strNodePath); //测试IsChildNodeOrAttr函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f3 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //测试IsChildNodeOrAttr函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f3 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //测试GetChildNodes函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //bool f5; //multimap<tstring, tstring> l_mapChildNodes; //if (l_bChildNodeOrAttribute) //{ // f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes); //} //测试GetChildNodes函数 //typ==int error //tstring l_strNodePath(_USERT("config.departments.department.info")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //bool f5; //multimap<tstring, int> l_mapChildNodes; //if (l_bChildNodeOrAttribute) //{ // f5 = GetChildNodes<int>(pt, l_strNodePath, l_mapChildNodes); //} //测试GetChildNodes函数 //tstring l_strNodePath(_USERT("config.departments.department")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //bool f5; //multimap<tstring, tstring> l_mapChildNodes; //if (l_bChildNodeOrAttribute) //{ // f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes); //} //测试GetCurrentNodeAttrs函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person")); //multimap<tstring, tstring> l_mapChildNodes; //bool f5 = GetChildNodes<tstring>(pt, l_strNodePath, l_mapChildNodes); //测试GetCurrentNodeAttrs函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person")); //bool l_bChildNodeOrAttribute; //int l_nChildNodeCount; //int l_nChildNodeAttributeCount; //bool f4 = IsChildNodeOrAttr(pt, l_strNodePath, l_bChildNodeOrAttribute, l_nChildNodeCount, l_nChildNodeAttributeCount); //bool f5; //map<tstring, tstring> l_mapChildNodeAttrs; //if (!l_bChildNodeOrAttribute) //{ // f5 = GetCurrentNodeAttrs<tstring>(pt, l_strNodePath, l_mapChildNodeAttrs); //} //测试GetChildNodesAttrs函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //bool f5; ////map<tstring, tstring> l_mapChildNodeAttrs; //multimap<tstring, map<tstring, tstring>> l_mmapChildNodesAttrs; //f5 = GetChildNodesAttrs<tstring>(pt, l_strNodePath, l_mmapChildNodesAttrs); //测试SetCurrentNodeValue函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //tptree::iterator iter= pt.get_child(l_strNodePath).begin(); //tstring l_strNodeValue = _USERT("testvalue"); //bool f6 = SetCurrentNodeValue(iter, l_strNodeValue); //测试SetCurrentNodeAttrValue函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>")); //tptree::iterator iter= pt.get_child(l_strNodePath).begin(); //tstring l_strNodeValue = _USERT("testvalue"); //bool f6 = SetCurrentNodeAttrValue(iter, l_strNodeValue); //测试DelCurrentNode函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //tptree &childpt = pt.get_child(l_strNodePath); //tptree::iterator iter = childpt.begin(); //bool f6 = DelCurrentNode(childpt, ++iter); //测试DelCurrentNode函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>")); //tptree &childpt = pt.get_child(l_strNodePath); //tptree::iterator iter = childpt.begin(); //bool f6 = DelCurrentNode(childpt, ++iter); //测试DelCurrentNodes函数 //tstring l_strNodePath(_USERT("config.departments.department.info")); //tptree &childpt = pt.get_child(l_strNodePath); //tptree::key_type kt = childpt.begin()->first; //tptree::size_type st6 = DelCurrentNodes(childpt, kt); //测试DelCurrentNodes函数 //tstring l_strNodePath(_USERT("config.departments.department.info.person.<xmlattr>")); //tptree &childpt = pt.get_child(l_strNodePath); //tptree::key_type kt = childpt.begin()->first; //tptree::size_type st6 = DelCurrentNodes(childpt, kt); //bool f2 = SaveXML(pt, l_strFileName2); cout << endl; }
testxml.xml测试文件:
<?xml version="1.0" encoding="utf-8"?> <config> <mainformsize height="600" width="330" top="50" left="500"/> <applicationtitle>GoCom统一通讯应用平台</applicationtitle> <loginmark> <fontsize>14</fontsize> <fontcolor>$0000ff</fontcolor> <lantern>true</lantern> <clientversion>5.3.5.17</clientversion> <serverip>imbs1.smartdot.com.cn</serverip> </loginmark> <departments> <department> <name>donghe</name> <level>2</level> <personcount>3</personcount> <info> <person id="1_1_1" name="王慧敏"/> <person id="1_1_2" name="刘东升"/> <person id="1_1_3" name="张智卓"/> </info> </department> <department> <name>boyun</name> <level>2</level> <personcount>3</personcount> <info> <person id="1_2_1" name="朗朗"/> <person id="1_2_2" name="隋国龙"/> </info> </department> </departments> </config>
注:代码可以正常运行在VS2010环境下,先下载安装boost库并添加到项目中,代码才能正常运行。
相关文章推荐
- boost::xml——基本操作以及中文乱码解决方案 (续)
- “用dom4j解析包”对xml进行dom方式操作中文乱码解决方案
- 用XMLHTTP Post/Get HTML页面时的中文乱码问题之完全Script解决方案
- Mantistbt系统导出excel为xml,以及csv 中文乱码问题解决
- Python操作MySQL以及中文乱码的问题
- C#操作MySQL时,出现的中文乱码的解决方案
- Hive(五)数据类型与库表操作以及中文乱码
- Python操作MySQL以及中文乱码的问题
- JSP或servlet中(以及上传下载文件)中文乱码或不显示的解决方案
- C#操作MySQL中文乱码的解决方案
- Qt国际化详细介绍,中文乱码以及解决方案
- 用xmlhttpRequest获取同域网页中文出现乱码解决方案
- JDBC操作Mysql数据库表时中文乱码的解决方案
- java 解析xml是使用dom4j空行以及中文乱码的处理
- (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
- windows命令行下对mysql 操作中文乱码完美解决方案
- Python操作MySQL以及中文乱码的问题
- C#操作MySQL中文乱码的解决方案
- jdbc操作非中文字符集oracle数据库导致的中文字符读写乱码的解决方案
- Python:UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 12305,以及中文乱码的解决方案