Easier XML With Boost

前端之家收集整理的这篇文章主要介绍了Easier XML With Boost前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
转自: http://www.fnord.ca/articles/xml.html

Introduction

As developers,we often want to save data from an object into a file with an XML based data format. The principle of loose coupling suggests that each object shouldn't produce its own XML code directly; there's no need for every class to know about XML. Even using an abstract representation of the XML format,such as a DOM tree,requires the class to know too much about XML. Also,writing XML is unnecessary low-level work for the developer. It's better to save to a simple,completely abstract format,and move elsewhere the details of how to save that format to XML. The Boost Serialization and Archive libraries allow this.

Serialization

To add serialization support to a class,you write a serialize() method that describes in what order the data fits into a generic archive. Here's an example:

#include <list>
#include <string>
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/nvp.hpp>

class italian_sandwich
{
    public:
        italian_sandwich();

    private:
        string m_bread,m_cheese;
        list<string> m_meats;
        bool m_spicy_eggplant_p;

    friend class boost::serialization::access;
    template<class archive>
    void serialize(archive& ar,const unsigned int version)
    {
        using boost::serialization::make_nvp;
        ar & make_nvp("Bread",m_bread);
        ar & make_nvp("Cheese",m_cheese);
        ar & make_nvp("Meats",m_meats);
        ar & make_nvp("Add Spicy Eggplant",m_spicy_eggplant_p);
    }
}


Notes:

  • The & operator becomes << when saving and >> when loading.
  • make_nvp() assigns a name to each element we want to save.
  • The unused version argument could be used later if we change the class.

Note how we didn't need to manually descend into the list of strings (m_meats) and serialize each string individually. As long as a type is serializable,STL containers of that type are serialized automatically. Similarly,if we built serialization support for one of our own classes,say a bread_t class,then we could still serialize the m_bread attribute with the same simple code,instead of manually descending into the m_bread object.

Archive

To save/load a serializable object to/from an XML file,we create a file stream,initialize an XML archive with that stream,and use the << or >> operator to write the object out to the archive or read it in. Here's an example using italian_sandwich:

#include <base/file_stream.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/nvp.hpp>

void save_sandwich(const italian_sandwich& sw,const string& file_name)
{
    typedef base::file_stream bafst;
    bafst::file_stream ofs(file_name,bafst::trunc | bafst::out);
    boost::archive::xml_oarchive xml(ofs);
    xml << boost::serialization::make_nvp("Italian Sandwich",sw);
}

italian_sandwich load_sandwich(const string& file_name)
{
    typedef base::file_stream bafst;
    italian_sandwich sw;
    bafst::file_stream ifs(file_name,bafst::binary | bafst::in);
    boost::archive::xml_oarchive xml(ifs);
    xml >> boost::serialization::make_nvp("Italian Sandwich",sw);
}


Notes:

  • Exception handling code is needed around the file_stream and archive initialization.
  • make_nvp() is not strictly necessary.

Further Examples

italian_sandwich was a very simple example class. It is easy to handle more complicated cases,for example:

  • If we can't modify a class directly,we can add a free serialization function outside it that uses only public methods. Its signature would look like:
    template<class archive>
    void serialize(archive& ar,italian_sandwich& sw,const unsigned int version);


    If the class has a method to save/load a data attribute (eg. for safety-checking),then the same code won't work for loading or saving to the archive. In that case we can split the serialize() method into save() and load():

    #include "bread_t.hpp"
    #include <boost/serialization/nvp.hpp>
    #include <boost/serialization/split_member.hpp>
    
    template<class archive>
    void load(archive& ar,const unsigned int version)
    {
        bread_t bread;
        ar & boost::serialization::make_nvp("Bread",bread);
        set_bread(bread);
        // load other ingredients...
    }
    
    template<class archive>
    void save(archive& ar,const unsigned int version)
    {
        const bread_t bread = get_bread();
        ar & boost::serialization::make_nvp("Bread",bread);
        // save other ingredients...
    }
    
    // define serialize() using save() and load()
    BOOST_SERIALIZATION_SPLIT_MEMBER();


    There are other archive formats,such as human readable text or binary formats. Once a class has serialization support,we can use any of those archive formats without changing the class.

    Conclusion

    Hopefully these two Boost libraries can prevent us from writing some unnecessary code.@H_502_76@@H_502_76@For further reference,see the@H_502_76@Boost documentation page.

原文链接:https://www.f2er.com/xml/299514.html

猜你在找的XML相关文章