Parsing xml
// Copyright 2014 Andrzej Krzemienski.
//
// This demonstrates how to use Boost.PropertyTree
// to read and write xml files.
#include <vector>
#include <string>
#include <fstream>
#include <locale>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
typedef boost::gregorian::date Date;
struct Flight
{
std::string carrier;
unsigned number;
Date date;
bool cancelled;
};
typedef std::vector<Flight> Sked;
class DateTranslator
{
typedef boost::date_time::date_facet<Date, char> tOFacet;
typedef boost::date_time::date_input_facet<Date, char> tIFacet;
std::locale locale_;
static std::locale isoDateLocale() {
std::locale loc;
loc = std::locale( loc, new tIFacet("%Y-%m-%d") );
loc = std::locale( loc, new tOFacet("%Y-%m-%d") );
return loc;
}
public:
typedef std::string internal_type;
typedef Date external_type;
DateTranslator( ) : locale_( isoDateLocale() ) {}
boost::optional<external_type> get_value(internal_type const& v)
{
std::istringstream stream(v);
stream.imbue(locale_);
external_type vAns;
if( stream >> vAns ) {
return vAns;
}
else {
return boost::none;
}
}
boost::optional<internal_type> put_value(external_type const& v)
{
std::ostringstream ans;
ans.imbue(locale_);
ans << v;
return ans.str();
}
};
namespace boost{ namespace property_tree{
template<> struct translator_between<std::string, Date> {
typedef DateTranslator type;
};
}}
Sked read( std::istream & is )
{
// populate tree structure pt
using boost::property_tree::ptree;
ptree pt;
read_xml(is, pt);
// traverse pt
Sked ans;
BOOST_FOREACH(ptree::value_type const&v, pt.get_child("sked")) {
if( v.first == "flight" ) {
Flight f;
f.carrier = v.second.get<std::string>("carrier");
f.number = v.second.get<unsigned>("number");
f.date = v.second.get<Date>("date");
f.cancelled = v.second.get("<xmlattr>.cancelled", false);
ans.push_back(f);
}
}
return ans;
}
void write( Sked sked, std::ostream & os )
{
using boost::property_tree::ptree;
ptree pt;
pt.add("sked.version", 3);
BOOST_FOREACH( Flight f, sked ) {
ptree & node = pt.add("sked.flight", "");
node.put("carrier", f.carrier);
node.put("number", f.number);
node.put("date", f.date);
if( f.cancelled ) node.put("<xmlattr>.cancelled", true);
}
write_xml(os, pt);
}
int main()
{
std::ifstream input("input.xml");
Sked sked = read( input );
std::ofstream output("output.xml");
write( sked, output );
return 0;
}
Like this:
Like Loading...
Hello,
please tell me how can I put polish font to xml.
I using something like this and in xml file there aren’t polish font:
@marto: It may not be that easy to do with Boost.PropertyTree library. Note that it is not designed to parse XML files in every aspect. Being able to parse XML is a side effect. That said, your problem can be solved, but with some additional effort. The thing is that ptree is using std::string inside, and std::string is ASCII-oriented and has no knowledge of non-ASCII characters, you would have to use another string type that is capable of storing non-ASCII characters, e.g., a UNICODE-aware string. ptree is just a typedef on:
If you change it into:
It should work, provided that you have some sort of utf8_string.
Thanks for answer, but this doesn’t work 😦
Try boost::property_tree::wptree instead
Missing a opening brace on line 84
Actually, it is there, if you scroll it to the right. Unfortunately, WordPress does not deal well with code examples with too long lines.
The issue I have with your code is that you are adding to namespace boost an overload that does not involve one of your types but instead a class in boost itself, so at some point in the future when they automatically support dates for property trees your code will cause a clash.
Property Tree functions take a 3rd parameters with a translator so you can just use that when you want to get or put the date. It may also be more efficient as you will want to reuse your DateTranslator (in particular the locale and its facets) rather than have it create a new one each time, which will happen if you use the standard one.
A very valid point. Thanks. I will update the example as soon as I have some free time to test it.