Help with saving Object to XML

I have a project which is a mainly a Canvas, with a drawing in it. Then like from the Webinar “The Clever Canvas” I am programatically including other canvas objects on the base canvas.

When I quit the program I want to save those canvas objects to an XML pref file, so that the same page can be recreated when the app is restarted.

I have found the array of mCanvasObjects in the Inspector window of the debugger. It is named &h60401057. The array members are the canvasObjects that I created, they also have similiar “names” (which I take to he hexadecimal).

When I look at each array member, I can see things like Top = 50 and so on, but then there are a whole lot of other hexadecimal numbers (?) for image files.

The project follows the sample project in the Clever Canvas Webinar in that I am including in the canvasObject an image labelled “Icon”. and a Label with a word in it.

So, when I read the XML file back in, do I have to create a new mCanvasObjects class with the name of &h60401057 and then append each of the individual Canvas objects including the ones with the hexadecimal “names”, using the same “names”? In other words, I think I have to completely recreate the apps memory as it appeared in the debugger.

The thing that worries me is, I can understand the use of the hexadecimal “names” because Xojo has no idea what they are (other than image files), but will the hexadecimal value always be the same on each run of the program. I ask this because, just like the sample program, I am including images in the computed canvasObject, but in some cases I am using the same image several times in each run of the program, but in the mCanvasObjects array the Picture [&h40F1D1F57] (for example) is different for each use of the same image.

I hope this makes some sense.

Those look like memory addresses, so you should ignore them. They’re not “names”. You will need to save enough information about each object - Top / Left / Image name (you should store that in the object in addition to the image if you want to save and restore it) / etc. - to be able to re-create the object when you read it back. Without knowing more about the project, it’s hard to give any specific advice.

You don’t store the OBJECTS - you store the data they hold

And hopefully you store it in a way that when you go to read it back in you can say “Hey this tis the data for an object of type X” and then you can create a new instance and read all the data into it

A GREAT example of exactly this is in fact the way the IDE stores the data that makes up your project.
Save as vcp or XML and look in the files & you’ll see what we do
And you can do the same after all the IDE IS just one huge Xojo project after all :stuck_out_tongue:

Thanks Tim

I wondered whether they were addresses, so you are right, I will ignore them. I did dabble with C once with all its pointers, and once is enough for me!

Norman, Thank you for your answer. I have never used the XML option for saving projects, so that’s my excuse for not thinking of that :slight_smile:

Anyway, that is the answer I am looking for. Luckily this is a private project that I am creating for my better half, so time is not restricted, and I am sure I am going to need heaps of it. Still, I only have to do it once, and hopefully I will be able to do it more quickly next time.

Many thanks to you both.

Ive just been doing exactly this.
I have a set of objects that have common properties, so I iterate through them and save the data.
Technically you can add a serialise method to each object, then when you read them back you can use the information about each type properly.

Heres some stripped down code I use to turn my objects into an XML document:

[code]Dim xml As New XmlDocument
dim x as integer
dim c as integer
dim o as ThingClass

c = objectList.count
Dim root As XmlNode
root = xml.AppendChild(xml.CreateElement(“MyFile”))

Dim Objects As XmlNode
dim Thing as XmlNode

Objects = root.AppendChild(xml.CreateElement(“Objects”))
for x = 0 to c
o = objectList(x) //this is an array of objects

  Thing = Objects.AppendChild(xml.CreateElement("Thing"))
  Thing.SetAttribute("ColorInner", o.ColorInner.tostring)
  Thing.SetAttribute("ColorOuter", o.ColorOuter.tostring)
  Thing.SetAttribute("Top", cstr(o.top))
  Thing.SetAttribute("Left", cstr(o.left))
  Thing.SetAttribute("Height", cstr(o.height))
  Thing.SetAttribute("Width", cstr(o.width))

next

return xml[/code]

loading it back is a question of

[code]dim x as XmlDocument
dim r as xmlnode
dim theObjects as XmlNodeList
dim anObject as xmlnode
dim i,z as integer
dim o as ThingClass

x = new xmldocument

x.LoadXml (thedoc)  //thedoc is the previously created XML document

theObjects = x.XQL("//Thing") // Find all usable nodes in XML

For i  = 0 To theObjects.Length-1
  anObject = theObjects.Item(i)
    o = new ThingClass    //probably want to add this to an array as you go along

    o.ColorInner = ColorFromHex(anObject.GetAttribute("ColorInner")) //color from hex just turns &cFF0000 into a colour
    o.ColorOuter = ColorFromHex(anObject.GetAttribute("ColorOuter"))
    o.Top = val(anObject.GetAttribute("Top"))
    o.left = val(anObject.GetAttribute("Left"))
    o.height = val(anObject.GetAttribute("Height"))
    o.Width = val(anObject.GetAttribute("Width"))
Next

[/code]

Jeff,

That is wonderful. As I said in a previous post, I have plenty of time to work this problem out, but on looking at it, the remainder of my life may not be enough. Just a quick look through what you have sent makes sense. I actually only want to save three items from the Canvas Object that I want to remember, the IconName (thanks Kem), the Top and the Left integers. With those three parameters, I can directly use the Method that is used to create the Canvas Objects in the first place (called from a pushbutton), and that should work. (I have tried it with hard-coded data, and it works OK. So I will see if I can get things to work.

Many thanks - just looking at how saving and loading XML was giving me a headache (it is the end of a long day here), you code is very clear.

Consider JSON as a simpler alternative. It’s much easier to work with.

XML has a stream API that lets you read an enormous file without having to load it all into memory
This lets you read a VERY large file without having to take it all into memory first
JSON doesn’t have such a mechanism
Its one reason I’d use XML despite JSON being easier to work with in many ways

Very cool Jeff, I was dabbling at doing a little interactive game and this will be very useful

Hi Kem

I was getting around to thinking that. I had a look at the XML class, and it looks complicated. Also, it boils down to the fact that I only need to store three values for each object that I want to save. All I need to do now is find out how to get access to them without the dreaded “that (something) doesn’t exist” in the debugger. But it is all fun, and I can’t do any damage with all the different things I try. So once I figure out access to the info I want, I will use JSON.

In that case, consider using my replacement JSON class. It does the same thing as the native, just faster. :slight_smile:

https://github.com/ktekinay/JSONItem_MTC

[quote=130063:@Kem Tekinay]In that case, consider using my replacement JSON class. It does the same thing as the native, just faster. :slight_smile:

https://github.com/ktekinay/JSONItem_MTC[/quote]

Thanks again,

We are out for about four hours, but I will definitely have a look at it when we get back home.