看到boost里面有个property_ptree库不错,于是到网上下载了一个xml文件测试了一下,还真的比较好用,觉得比tinyXML库还好用,使用方法比较简单。
该库还可以解析ini, info, json文件,但我没试过。
xml文件大小为223kb,解析完如果不在命名窗口进行输出用了7s左右。
获得元素值使用ptree类的成员模板函数get,在模板参数中说明数据类型,在参数列表中填写路径,路径的表示也很简况,之间用点号分隔。
获得元素属性只需要在路径中的属性名称前面加上标记就可以了,还有获得注释等。
对于有多个子元素的元素结点,我们可以使用getChild()来获得它的子结点,然后就可以像使用STL中的迭代器一样对子元素进行遍历操作。
注意get和getChild的路径参数,多调试一下也是极好的。
具体用法可以参照下面的代码:
注意在使用get方法时最好给出第二个参数用作默认值,这样如果没有找到该属性,函数会返回该默认值,否则,程序会崩溃,最好对getChild
方法进行异常的捕获,以提高程序的鲁棒性。
文件结构复杂度适中:
解析代码如下:
#include
#include
#include
#include
#include
#include
#include
#include "boost/timer.hpp"
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/xml_parser.hpp"
#include "boost/property_tree/exceptions.hpp"
using namespace std;
struct _head
{
wstring revMajor;
wstring revMinor;
wstring name;
wstring version;
wstring date;
wstring north;
wstring south;
wstring east;
wstring west;
wstring maxRoad;
wstring maxJunc;
wstring maxPrg;
};
struct _predecessor
{
wstring elementType;
wstring elementId;
wstring contactPoint;
};
struct _link
{
_predecessor predecessor;
_predecessor successor;
};
struct _geometry
{
wstring s;
wstring x;
wstring y;
wstring hdg;
wstring length;
};
typedef vector<_geometry> planView_vec;
struct _elevationProfile
{
wstring s;
wstring a;
wstring b;
wstring c;
wstring d;
};
struct _superelevation
{
wstring s;
wstring a;
wstring b;
wstring c;
wstring d;
};
typedef vector<_superelevation> lateralProfile_vec;
struct _road
{
wstring name;
wstring length;
wstring id;
wstring junction;
_link link;
planView_vec planeView;
_elevationProfile elevationProfile;
lateralProfile_vec lateralProfile;
//... more
//lanes
//objects
//signals
};
typedef vector<_road> road_vec;
struct _junction
{
wstring name;
wstring id;
//... more
//connection
//
};
typedef vector<_junction> junction_vec;
struct _OpenDriveXML
{
_head head;
road_vec road_vc;
junction_vec junction_vc;
};
//////////////////////////////////////////////////////////////////////////
int main()
{
typedef boost::property_tree::basic_ptree::value_type _value_type;
typedef boost::property_tree::basic_ptree _self_type;
boost::property_tree::wptree pt;
_OpenDriveXML OD_xml;
boost::timer tm;
boost::property_tree::xml_parser::read_xml("E:\\vs2013 programs\\ACM_NYOJ_Solution\\Win32\\Debug\\Bin\\sample1.xml", pt);
//par_xml.head.date =
wstring par = pt.data();
wstring itr = pt.get(_T("OpenDRIVE.header..revMajor"));
//boost::property_tree::ptree planeview_tr = pt.get_child(_T("OpenDRIVE.road.planView"));
_self_type odChild = pt.get_child(_T("OpenDRIVE"));
for (auto itr = odChild.begin(); itr != odChild.end(); ++itr)
{
if (itr->first == _T("header"))
{
OD_xml.head.revMajor = itr->second.get(_T(".revMajor"));
OD_xml.head.revMinor = itr->second.get(_T(".revMinor"));
OD_xml.head.name = itr->second.get(_T(".name"));
OD_xml.head.version = itr->second.get(_T(".version"));
OD_xml.head.date = itr->second.get(_T(".date"));
OD_xml.head.north = itr->second.get(_T(".north"));
OD_xml.head.south = itr->second.get(_T(".south"));
OD_xml.head.east = itr->second.get(_T(".east"));
OD_xml.head.west = itr->second.get(_T(".west"));
OD_xml.head.maxRoad = itr->second.get(_T(".maxRoad"));
OD_xml.head.maxJunc = itr->second.get(_T(".maxJunc"));
OD_xml.head.maxPrg = itr->second.get(_T(".maxPrg"));
}
if (itr->first == _T("road"))
{
// road
_road rd;
// link
rd.link.predecessor.elementType = itr->second.get(_T("link.predecessor..elementType"), _T(""));
rd.link.predecessor.elementId = itr->second.get(_T("link.predecessor..elementId"), _T(""));
rd.link.predecessor.cOntactPoint= itr->second.get(_T("link.predecessor..contactPoint"), _T(""));
rd.link.successor.elementType = itr->second.get(_T("link.predecessor..elementType"), _T(""));
rd.link.successor.elementId = itr->second.get(_T("link.predecessor..elementId"), _T(""));
rd.link.successor.cOntactPoint= itr->second.get(_T("link.predecessor..contactPoint"), _T(""));
// geomeotry
_geometry geo;
planView_vec pa_vc;
_self_type pv_tr = itr->second.get_child(_T("planView"));
for_each(pv_tr.begin(), pv_tr.end(), [&](const _value_type &_vt)
{
rd.elevationProfile.a = _vt.first;
geo.s = _vt.second.get(_T(".s"), _T(""));
geo.x = _vt.second.get(_T(".x"), _T(""));
geo.y = _vt.second.get(_T(".y"), _T(""));
geo.hdg = _vt.second.get(_T(".hdg"), _T(""));
geo.length = _vt.second.get(_T(".length"), _T(""));
pa_vc.push_back(geo);
});
rd.planeView = pa_vc;
// elevationProfile
rd.elevationProfile.a = itr->second.get(_T("elevationProfile.elevation..a"), _T(""));
rd.elevationProfile.b = itr->second.get(_T("elevationProfile.elevation..b"), _T(""));
rd.elevationProfile.c = itr->second.get(_T("elevationProfile.elevation..c"), _T(""));
rd.elevationProfile.d = itr->second.get(_T("elevationProfile.elevation..d"), _T(""));
rd.elevationProfile.s = itr->second.get(_T("elevationProfile.elevation..s"), _T(""));
// superelevation
_self_type itr_sup = itr->second.get_child(_T("lateralProfile"));
lateralProfile_vec lat_vc;
_superelevation sup;
for_each(itr_sup.begin(), itr_sup.end(), [&](const _value_type &_vt)
{
sup.a = _vt.second.get(_T(".a"), _T(""));
sup.b = _vt.second.get(_T(".b"), _T(""));
sup.c = _vt.second.get(_T(".c"), _T(""));
sup.d = _vt.second.get(_T(".d"), _T(""));
sup.s = _vt.second.get(_T(".s"), _T(""));
lat_vc.push_back(sup);
});
rd.lateralProfile = lat_vc;
OD_xml.road_vc.push_back(rd);
}
else if (itr->first == _T("junction"))
{
_junction junc;
junc.name = itr->second.get(_T(".name"), _T(""));
junc.id = itr->second.get(_T(".id"), _T(""));
OD_xml.junction_vc.push_back(junc);
}
}
wcout <<_T("OD_XML:") <
命名提示符下的输出: