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

时间:2022-05-27 22:34:05

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

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', , L"utf-8");
#else
std::locale current_locale;
boost::property_tree::xml_parser::xml_writer_settings<char> settings('\t', , "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 ; //no child
}
else
{
return ; //have child or attribute
}
}
catch (const std::exception &e)
{
cout << "Error:" << typeid(e).name() << ": ";
cout << e.what() << endl;
return -; //error: exception
} return -;
} //查看是否有子节点或者属性,如果没有则返回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 = ; //initialize child node count
o_nChildNodeAttributeCount = ; //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 (==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 (==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 (!=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 (==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 (==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 (==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 -; //error: exception
} return -;
} 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>
<*>true</*>
<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库并添加到项目中,代码才能正常运行。​