Friday 25 July 2014

XML with Linq - how to save and load those files?! [Unity3D]

Recently I was fighting with saving and loading XML files using Linq which was quite odd.. Especially when this make you headache..


Some of you may not even think about it when you have some small projects but in bigger one.. Data serialization might be real challenge. I was doing some research for dealing with it and I found 2 most common methods: 
  • Unity Serialization, which work automatic with just adding [SerializeField] over variable or class
  • Writing own serializer and save data to XML, JSON or any other file
First I was thinking that the first method might be good for me but suddenly... Wild "I'm not this type of guy" appear.. And that mean that I have to know what's going on in project so I start digging and looking for information about dealing with XMLs... :P

When I end reading some articles about it I think "meh, that will be easy" and it was at the beginning...
Simple add few usings..
using System.IO; 
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
Create XElement (or XDocument)... I suggest to create it with some root name.
For example:
XElement xEle = new XElement("XRoot");
Than you can create even more elements inside elements! And there is 2 way to do that ;)

I. Create elements separately

XElement el1 = new XElement("First");
XElement el2 = new XElement("Second");
 el1.Add(el2);

II. Put everything inside!

XElement el1 = new XElement("First",
                new XElement("Second"),                new XElement("Third"),                new XElement("WithInt", 325),                new XElement("WithString", "really?"),
                new XElement("WithKids", new XElement("Kid")) 
);

This is your choice which one you will use ;)
And at the end of creating this thing you have to save it.
xEle.Save("SomeXElements.xml");
By default this method save file in your main project folder. If you would rather to have it in Assets folder you have to do this:
xEle.Save(Application.dataPath + @"Assets/" + "SomeXElements.xml");
@ means that all characters in this string with be treat like there are. (Dashes, slashes and all this weird formatting stuff)

GREAT! LET THE HORROR BEGIN!

Yeah.. That was something like that.. 
So we have saved file and now we have to load that file.
if (File.Exists("SomeXElements.xml")){
XElement xEle = XElement.Load("SomeXElements.xml"); 
// moar code!!
}
If you're dealing with XML file that have multiple element with same name than you have to find all those elements. Watch out! Linq! :O
IEnumerable<XElement> someElements = 
                from el in xEle.Elements("SomeElements") 
                select el;

This should find all "SomeElements" elements in our xEle (root node).
I was getting hard time to understand how this work but I think I got it.


Of course you can gave more precise question but for basic use this is enough.

Now we have collection of "SomeElements" and we'd like to get some individual values from inside of them.

            foreach (XElement el in someElements)
            {
                int number = (int)el.Element("number");
                string someString = (string)el.Element("myName");
            }


And now we have values. If you need to load other type of data than you probably need just cast to desire type or you will have to write parser (soon I'll put some example for enums).

And this is it.
If you need more information about XElements than I recommend visit Microsoft MSDN Library [here].
If you need more information about Unity Serializer than go [here] and [here].
And finally if you are interested in example script than go to my repository [here].

To the next time! ;)

No comments:

Post a Comment