Creating XML text data automatically through serialization

Another way to create XML data structures from game objects and properties is by serializing the contents of an object automatically. This technique automatically generates XML for all the public properties of an object.

Getting ready

In the 0423_08_06 folder, you'll find the listings for all four classes described in this recipe.

How to do it...

To create XML text data through serialization, perform the following steps:

  1. Create a C# script called PlayerScore:
    // file: PlayerScore.cs
    public class PlayerScore 
    {
        public string name; 
        public int score;
    
        // default constructor, needed for serialization
        public PlayerScore() {}
    
        public PlayerScore(string newName, int newScore) {
            name = newName;
            score = newScore;
        }
    }
  2. Create a C# script called SerializeManager:
    // file: SerializeManager.cs
    //
    // acknowledgements - this code has been adapted from:
    //www.eggheadcafe.com/articles/system.xml.xmlserialization.asp
    using System.Xml;
    using System.Xml.Serialization;
    using System.IO;
    using System.Text;
    using System.Collections.Generic;
    
    public class SerializeManager<T> {
        public string SerializeObject(T pObject) {
            string XmlizedString = null;
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer xs = new XmlSerializer(typeof(T));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
            xs.Serialize(xmlTextWriter, pObject);
            memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
            XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
            return XmlizedString;
        }
    
        public object DeserializeObject(string pXmlizedString) {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
            return xs.Deserialize(memoryStream);
        }
    
        private string UTF8ByteArrayToString(byte[] characters) {
            UTF8Encoding encoding = new UTF8Encoding();
            string constructedString = encoding.GetString(characters);
            return (constructedString);
        }
    
        private byte[] StringToUTF8ByteArray(string pXmlString) {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }
    }
  3. Add the following C# script class to Main Camera:
    // file: SerialiseToXML.cs
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class SerialiseToXML : MonoBehaviour {
        private string output = "(nothing yet)";
    
        void Start () {
            SerializeManager<PlayerScore> serializer = new SerializeManager<PlayerScore>();
            PlayerScore myData = new PlayerScore("matt", 200);
            output = serializer.SerializeObject(myData);
        }
    
        void OnGUI() {
            GUILayout.Label( output );
        }
    }
  4. Run your game. You should see XML data displayed as a label on the screen.

How it works...

The Start() method creates serializer, a new SerializeManager() object for objects of the PlayerScore class. A new PlayerScore object, myData, is created with the values "Matt" and 200. The serializer object is then passed the myData object, and the XML text data is returned as a string and stored in output. Our OnGUI() method displays the contents of output.

Note

The SerializeManager class has been adapted from the code published by EggHeadCafe at the following URL:

www.eggheadcafe.com/articles/system.xml.xmlserialization.asp

You shouldn't need to worry too much about understanding all the code in this class—unless you want to :-). We have adapted the class so that it can be used for any data object class via C# generics; all you need to do is the following:

  • Replace <PlayerScore> with <YourDataClassName> when declaring and creating an instance of SerializationManager; in our example, this is in the first statement of the Start() method
  • Pass in an object of your class as the argument to serializer.SerializeObject()
  • Ensure that your data class has a default constructor (that is public and takes no arguments)
  • Make sure each property that you want included in the generated XML is public

Note

The following site is a good place to learn more about Unity XML serialization:

http://wiki.unity3d.com/index.php?title=Saving_and_Loading_Data:_XmlSerializer

There's more...

Some details you don't want to miss:

Protecting member properties with accessor methods

Just having public properties is generally considered poor practice, because any part of an application with a reference to an object can make any kind of changes to those properties. However, if you wish to use this serialization recipe, you have to have public properties.

A good solution is to provide public accessor methods, which behave like public properties but allow you to add a validation code behind the get/set methods for each corresponding hidden private property. Here, we have provided such an improved implementation of the PlayerScore class, PlayerScore2. Data is stored in the private variables _name and _score; they are accessed via the public variables Name and Score, which have get/set statements that handle changes to the private variables, and for which the appropriate validation logic could be implemented (for example, only changing Score if the new score is zero or higher, to prevent negative scores):

// file: PlayerScore2.cs
using System.Xml.Serialization;

[XmlRoot("player_score_2")]
public class PlayerScore2 
{
    private string _name; 
    private int _score;

    [XmlElement("name")]
    public string Name {
        get{ return _name; }
        set{ _name = value; }
    }

    [XmlElement("score")]
    public int Score {
        get{ return _score;}
        set{ _score = value;}
    }

    // default constructor, needed for serialization
    public PlayerScore2() {}

    public PlayerScore2(string newName, int newScore) {
        Name = newName;
        Score = newScore;
    }
}

Note

Variable naming styles vary between programmers and organizations. One approach to naming private member variables is to prefix them with an underscore (as we have done in the previous code snippet). An alternative, which some programmers prefer, involves using no underscore and disambiguating the argument of a setter method from the member variable with the same identifier by using keyword this; for example, this.name = name.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.12.186