[C++] Objects reading XML

Started by
4 comments, last by Mybowlcut 15 years, 4 months ago
Hey. I'm currently trying to replace all the IO between my game and text files with IO between the game and XML files. Just wondering what the best way to read objects from XML files is... Should I make non-member friend functions in each object that can be loaded from an XML file? Or should I make a member function called Read or something that is a virtual function carried down from a XML_Readable abstract class? Is it also possible to somehow use operator>> and derive a class from std::istream for this? Or would it not work? Cheers.

Advertisement
My solution was to go with the fact that Xml documents are trees.

So I just created a XMLNode class that was a descended from my TreeList object (link list tree, i.e, it has children as well as siblings). I then have some recursive search functions going depth and breadth. It works well enough.

My thought: XML should be expected to be well formed and matching your schema, if it isn't fail gracefully its the best way, and then lecture yiur user about garbage in garbage out :)
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.
Just use a library. There are all kinds of them.
I'm partial towards TinyXML, because you only need to include a handful of files and it has both read and write support. It doesn't support more advanced things like DTDs or XSLs, but for basic XML it's wonderful.
I've used Xerces and TinyXML in C++.

Tiny is probably what you want. It's easy to use, and reasonably quick.

Xerces is best for when you want to use the whole 9 barreled rotating shotgun features of XML. Xpath queries are really convenient, but I never found it particularly snappy.
Hey guys.

Sorry, I should have mentioned that I'm already using TinyXML(++).

I was actually wondering about the best way to read/write game objects using TinyXML. The TinyXML documentation says that there are overloaded insertion/extraction operators for some classes, so I was wondering if I should go with using >>/<< or make my own Read/Write functions.

Edit: Quotes won't take tabs or spaces so excuse the indentation, but as an example, I'd have an XML file for a Level that looks something like this (I don't know the proper format yet, but this is just an example):
Quote:<?xml version="1.0" ?>
<level width="10" height="10">
<background_tiles>
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" /> <tile name="tile2.png" /> <tile name="tile2.png" />
<tile name="tile2.png" />
</background_tiles>
<object_tiles>
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="portal.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="tree_bottom.png" passability="2" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" /> <object_tile name="blank.png" passability="1" />
<object_tile name="blank.png" passability="1" />
</object_tiles>
<foreground_tiles>
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="tree_top.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" /> <tile name="blank.png" /> <tile name="blank.png" />
<tile name="blank.png" />
</foreground_tiles>
<portals>
<portal to_level="level2" from_x="1" from_y="1" to_x="4" to_y="4" />
</portals>
</level>


So far, I've got something like this going for writing it to an XML file (I haven't tested it yet):
void Level::Write_Tiles(ticpp::Element* root, const std::string& type, tile_vector& v){	using namespace ticpp;	Element* tile = NULL;	Element* tiles = new Element(type);	root->LinkEndChild(tiles);	for(tile_it it = v.begin(); it != v.end(); ++it)	{ // Write each background tile.		tile = new Element("tile");		tile->SetAttribute("name", it->File_Name());		tiles->LinkEndChild(tile);	}}void Level::Write_Object_Tiles(ticpp::Element* root){	using namespace ticpp;	Element* tile = NULL;	Element* object_tiles = new Element("object_tiles");	root->LinkEndChild(object_tiles);	for(object_tile_it it = this->object_tiles.begin();	it != this->object_tiles.end(); ++it)	{ // Write each background tile.		tile = new Element("object_tile");		tile->SetAttribute("name", it->File_Name());		tile->SetAttribute("passability", static_cast<int>(it->Passability()));		object_tiles->LinkEndChild(tile);	}}void Level::Write_Portals(ticpp::Element* root){	using namespace ticpp;	Element* portal = NULL;	Element* portals = new Element("portals");	root->LinkEndChild(portals);	for(portal_it it = this->portals.begin();	it != this->portals.end(); ++it)	{ // Write each background tile.		portal = new Element("portal");		portal->SetAttribute("to_level", it->To_Level());		portal->SetAttribute("from_x", it->From_Pos().y);		portal->SetAttribute("from_y", it->From_Pos().y);		portal->SetAttribute("to_x", it->To_Pos().x);		portal->SetAttribute("to_y", it->To_Pos().y);		portals->LinkEndChild(portal);	}}void Level::Write(const std::string& file_name){	using namespace ticpp;	Document document;	Element* tile = NULL;	Declaration* dec = new Declaration("1.0", "", "");	document.LinkEndChild(dec);	Element* root = new Element("level");	document.LinkEndChild(root);	root->SetAttribute("width", size.x);	root->SetAttribute("height", size.y);	Write_Tiles(root, "background_tiles", background_tiles);	Write_Object_Tiles(root);	Write_Tiles(root, "foreground_tiles", foreground_tiles);	Write_Portals(root);}


[Edited by - Mybowlcut on November 22, 2008 5:42:07 AM]

This topic is closed to new replies.

Advertisement