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;
}

6 Responses to Parsing xml

  1. marto says:

    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:

    ptree pt;
    ptree & tresc1 = pt.add("nazwaroota.tresc", "");
    tresc1.put("coś", "źle");
    write_xml("testXml.xml", pt);
    
    • @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:

      typedef basic_ptree< std::string, std::string > ptree;
      

      If you change it into:

      typedef basic_ptree< utf8_string, utf8_string > ptree;
      

      It should work, provided that you have some sort of utf8_string.

  2. Carlos Cortijo says:

    Try boost::property_tree::wptree instead

  3. Missing a opening brace on line 84

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s