I'm using C++ boost::serialization
library to read and write configuration XMLs. To provide backward compatibility to the user, while reading an XML if some XML elements are absent, it needs to have default values. It will throw input stream error
if the xml element that it is trying read is missing.
I tried using Try-Catch blocks to solve this, but this way also i'm getting the input stream error
.
void XmlAttributes::serialize(Archive & ar, const unsigned int file_version ){
ar & boost::serialization::make_nvp("Attr1",attr1);
try {
ar & boost::serialization::make_nvp("Attr2", attr2);
}
catch (boost::archive::archive_exception const& e) {
// XML element not found, set default value
attr2 = true; // Set a default value, for example, true
}
}
In the above code "Attr1" is mandatory one in the XML, but "Attr2" is optional element, so it should default to 'true' if it doesn't exist in the XML without any input stream errors. Is there any way to use boost optional
libraries to solve this issue.
Boost Serialization does not deal with XML attributes. It deals with XML archives.
You control serialization by defining serialization for your type.
If you need backwards compatibility you need to version that definition. Luckily, Boost Serialization allows you to do just that: https://www.boost.org/doc/libs/1_84_0/libs/serialization/doc/
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <fstream>
#include <iostream>
#include <set>
using boost::serialization::make_nvp;
struct XmlAttributes {
XmlAttributes(std::string attr1 = {}, bool attr2 = false) //
: attr1(std::move(attr1))
, attr2(attr2) {}
private:
std::string attr1;
bool attr2;
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive& ar, unsigned version) {
if (Archive::is_loading::value)
std::cout << "Loading version: " << version << std::endl;
else
std::cout << "Saving version: " << version << std::endl;
ar& make_nvp("Attr1", attr1);
if (version >= 1)
ar& make_nvp("Attr2", attr2);
else
attr2 = true; // Set a default value, for example, true
}
friend std::ostream& operator<<(std::ostream& os, XmlAttributes const& attr) {
return os << "Attr1: " << attr.attr1 << ", Attr2: " << attr.attr2;
}
};
#ifdef NEWVERSION
BOOST_CLASS_VERSION(XmlAttributes, 1)
#endif
int main(int argc, char** argv) {
std::cout << "\n---\nProgram Version: " << boost::serialization::version<XmlAttributes>::value << std::endl;
std::set<std::string_view> args(argv, argv + argc);
if (args.contains("load")) {
XmlAttributes attr;
std::ifstream ifs("test.xml");
boost::archive::xml_iarchive(ifs) >> make_nvp("test", attr);
std::cout << attr << std::endl;
}
if (args.contains("save")) {
XmlAttributes attr
{"Hello", false};
std::ofstream ofs("test.xml");
boost::archive::xml_oarchive(ofs) << make_nvp("test", attr);
}
}
Testing by saving with old version, loading and saving it again with the new version:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_serialization -o oldversion
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_serialization -o newversion -DNEWVERSION
./oldversion save
nl test.xml
./newversion load save
nl test.xml
./oldversion load
Shows
---
Program Version: 0
Saving version: 0
1 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2 <!DOCTYPE boost_serialization>
3 <boost_serialization signature="serialization::archive" version="20">
4 <test class_id="0" tracking_level="0" version="0">
5 <Attr1>Hello</Attr1>
6 </test>
7 </boost_serialization>
---
Program Version: 1
Loading version: 0
Attr1: Hello, Attr2: 1
Saving version: 1
1 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2 <!DOCTYPE boost_serialization>
3 <boost_serialization signature="serialization::archive" version="20">
4 <test class_id="0" tracking_level="0" version="1">
5 <Attr1>Hello</Attr1>
6 <Attr2>0</Attr2>
7 </test>
8 </boost_serialization>
---
Program Version: 0
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): class version 13XmlAttributes
Interactive demonstration for clarity: