I'm trying to serialize my classes to xml. My classes;
class HardwareDto{
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(HardwareID);
ar & BOOST_SERIALIZATION_NVP(HardwareHostID);
ar & BOOST_SERIALIZATION_NVP(HardwareFriendlyName);
}
public:
int HardwareID;
int HardwareHostID;
string HardwareFriendlyName;
inline HardwareDto(int HardwareHostID, int HardwareID, string HardwareFriendlyName) {
this->HardwareHostID = HardwareHostID;
this->HardwareID = HardwareID;
this->HardwareFriendlyName = HardwareFriendlyName;
}
};
And a class which contains a HardwareDto
list.
class HardwareHostDto {
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(HardwareHostID);
ar & BOOST_SERIALIZATION_NVP(BranchID);
ar & BOOST_SERIALIZATION_NVP(HardwareHostFriendlyName);
ar & BOOST_SERIALIZATION_NVP(HardwareList);
}
public:
int HardwareHostID;
int BranchID;
string HardwareHostFriendlyName ;
HardwareDto* HardwareList[20];
inline HardwareHostDto(int HardwareHostID, int BranchID, string HardwareHostFriendlyName, HardwareDto* HardwareList[20]) {
this->HardwareHostID = HardwareHostID;
this->BranchID = BranchID;
this->HardwareHostFriendlyName = HardwareHostFriendlyName;
this->HardwareList[0] = HardwareList[0];
}
};
And
HardwareDto *HardwareList[20];
is my global hardwaredto list. In this example I only inserted one hardwarehostdto object into this list.
I'm trying to serialize this via boost function:
std::ofstream ofs("filename.xml");
unsigned int flags = boost::archive::no_header;
boost::archive::xml_iarchive ia(is, boost::archive::no_header);
boost::archive::xml_oarchive oa(ofs, flags);
HardwareHostDto* HardwareHost = new HardwareHostDto(1, 1, "kiosk", HardwareList);
oa << BOOST_SERIALIZATION_NVP(HardwareHost);
After this code executed, i got this filename.xml:
<HardwareHost class_id="0">
<HardwareHostID>1</HardwareHostID>
<BranchID>1</BranchID>
<HardwareHostFriendlyName>kiosk</HardwareHostFriendlyName>
<HardwareList>
<count>20</count>
<item class_id="1">
<HardwareID>2</HardwareID>
<HardwareHostID>2</HardwareHostID>
<HardwareFriendlyName>Ankara</HardwareFriendlyName>
</item>
</HardwareList>
</HardwareHost>
<item>
tag should be <Hardware>
but i cant change it.
My question is: is there any way to change <item>
tag, or actullay customize this xml structure, like no <count>
tag or flags? I found a few ways to do it in boost website but couldnt handle it.
Thank you.
Yes, you can hack it. Maybe. To an extent. See:
And no, you shouldn't. Use an XML library to write arbitrary XML.
Boost Serialization only does serialization. The archive format is implementation detail.
Bad Example
What not to do (it breaks non-default constructible types, it breaks versioning).
On the bright side, this code doesn't leak memory.
Live On Coliru
Prints
And writes the XML as:
What To Do
Using an XML library. This calls for (a lot) generalization, but here's a start using PugiXML:
LiveOn ColiruWhich also prints
And writes a
test.xml
:In order to fully customize XML output from boost serialization you can write your own XML archive. It's a three step process:
TextOPrimitiveOnXML
.BasicXMLOArchive
. This is the class that will write XML tags.XMLOArchive
.The advantage is that not only you can reuse your
serialize
code, but also you can use different backends. For example, you can have an archive that creates a DOM right away instead of merely text output.Here are skeletons for the classes I mentioned.
TextOPrimitiveOnXML
, itssave
methods define writing of primitive types.BasicXMLOArchive
, this is where you manipulate tags and attributes:The final glue: