Loading a single value from XML file in C#

  • (2 Pages)
  • +
  • 1
  • 2

18 Replies - 7617 Views - Last Post: 17 September 2010 - 04:44 AM Rate Topic: -----

#1 xZachtmx   User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 125
  • Joined: 14-June 09

Loading a single value from XML file in C#

Posted 14 September 2010 - 04:10 PM

Hey guys! I am using the XNA game studio for a simple game (I am still learning). So i want to store a high score in an xml file (that seems the easiest for now).

So I made a class called storage with a saveScore and loadScore function. I got the code for savescore working:
        public void saveScore(int score)
        {
            XmlWriterSettings appearance = new XmlWriterSettings();
            appearance.Indent = true;
            XmlWriter xml = XmlWriter.Create(AppDomain.CurrentDomain.BaseDirectory + "Score.xml", appearance);

            xml.WriteStartDocument();
            xml.WriteStartElement("Score");
          
            xml.WriteElementString("score", score.ToString());

            xml.WriteEndElement();
            xml.WriteEndDocument();
            xml.Flush();
            xml.Close();
        }


so if i did storage.saveScore(666);

the score.xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Score>
  <score>666</score>
</Score>



The only thing i am having trouble with is loading the <score> tag back into the game as in int so if i called storage.loadGame(); it would return 666 as an integer.

Can anyone help?

Thanks!
Zach

Is This A Good Question/Topic? 0
  • +

Replies To: Loading a single value from XML file in C#

#2 JackOfAllTrades   User is offline

  • Saucy!
  • member icon

Reputation: 6246
  • View blog
  • Posts: 24,014
  • Joined: 23-August 08

Re: Loading a single value from XML file in C#

Posted 14 September 2010 - 04:11 PM

So...where's your loadScore() method so we can take a look?
Was This Post Helpful? 0
  • +
  • -

#3 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6532
  • View blog
  • Posts: 14,447
  • Joined: 02-June 10

Re: Loading a single value from XML file in C#

Posted 14 September 2010 - 04:22 PM

*
POPULAR

I'm really lazy. Id make the score a serializable object and let the framework handle the details.
myObj would be your score object

        void SaveSettings()
        {

            //Export as XML serialized
            var x = new System.Xml.Serialization.XmlSerializer(myObj.GetType());
            x.Serialize(Console.Out, myObj);
            string NewPathName = SaveFolder.TrimEnd('\\') + "\\" + Path.ChangeExtension(ScoreFileName, "xml");
            using (var sw = new StreamWriter(NewPathName, false))
            {
                x.Serialize(sw, myObj);
            }
         }




                        

                        // A FileStream is needed to read the XML document.
                        using (FileStream fs = new FileStream(ScoreXmLfile, FileMode.Open))
                        {
                            XmlReader reader = new XmlTextReader(fs);
                            // Use the Deserialize method to restore the object's state.
                            MyScoreObj = (ScoreObj)serializer.Deserialize(reader);
                        }


This post has been edited by tlhIn'toq: 14 September 2010 - 04:23 PM

Was This Post Helpful? 6
  • +
  • -

#4 Imdsm   User is offline

  • D.I.C Regular
  • member icon

Reputation: 104
  • View blog
  • Posts: 362
  • Joined: 21-March 09

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 05:34 AM

Great idea tlhIn'toq, I'll probably do that in future, saves a lot of work!
Was This Post Helpful? 0
  • +
  • -

#5 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5103
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 07:44 AM

I always see a lot about serialization, but I never see much about using the LINQ to XML classes. They're pretty simple, especially for just a single value, where serialization might be a bit overkill.

Here's how I would do what you're doing. This snippet would create an initial file:
string path = @"c:\dev\scores.xml";
int score = 500;
XElement e = new XElement("scores");
e.Add(new XElement("highScore", score));
e.Save(path);



The output is:

<?xml version="1.0" encoding="utf-8"?>
<scores>
  <highScore>500</highScore>
</scores>


Loading is just as easy:

string path = @"c:\dev\scores.xml";
XElement e = XElement.Load(path);
int scores = int.Parse(e.Element("highScore").Value);

Was This Post Helpful? 3
  • +
  • -

#6 Robin19   User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 08:12 AM

I have a question/problem that relates to tlhIn'toq's answer.

This is all in testing, I just wanted to learn this code for future use. I was able to get it to run beautifully using a simple serialized class. I then wanted to use a class inside a class to create a more complex XML file structure. (Simple Properties and Constructors cut out):
    [Serializable()]
    public class Player
    {
        private string _name;
        public string Name ...

        private Save _save;
        public Save Progress ...

        // ... Constructors cut

        public Player(SerializationInfo info, StreamingContext ctxt)
        {
            Name = (string)info.GetValue("Name", typeof(string));
            Progress = (Save)info.GetValue("Save", typeof(Save));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", Name);
            info.AddValue("Save", Progress);
        }

        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("Name: ");
            builder.Append(Name);
            builder.Append("\n");
            builder.Append(Progress);
            return builder.ToString();
        }
    }

    [Serializable()]
    public class Save
    {
        private int _score;
        public int Score ...

        private int _level;
        public int Level ...

        public Save(int Score, int Level) ...
                        
        public Save(SerializationInfo info, StreamingContext ctxt)
        {
            Level = (int)info.GetValue("Level", typeof(int));
            Score = (int)info.GetValue("Score", typeof(int));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Level", Level);
            info.AddValue("Score", Score);
        }

        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("\t");
            builder.Append("Level: ");
            builder.Append(Level);
            builder.Append("\n");
            builder.Append("\t");
            builder.Append("Score: ");
            builder.Append("\n");
            return builder.ToString();
        }
    }


Here is the Main class:
        static void Main(string[] args)
        {
            Player Todd = new Player("Todd", 5, 77);
            SaveSettings(Todd);
            Console.WriteLine("Todd:\n{0}", Todd);
            Console.ReadLine();

            Player Todd2 = GetSettings();
            Console.WriteLine("Todd2:\n{0}", Todd2);
            Console.ReadLine();
        }

        public static void SaveSettings(Player player)
        {
            var x = new System.Xml.Serialization.XmlSerializer(player.GetType());
            string NewPathName = System.IO.Path.ChangeExtension("Scores", "xml");
            using (var writer = new System.IO.StreamWriter(NewPathName, false))
            {
                x.Serialize(writer, player);
            }
        }

        public static Player GetSettings()
        {
            Player player = new Player();
            using (System.IO.FileStream stream = new System.IO.FileStream("Scores.xml", System.IO.FileMode.Open))
            {
                System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(stream);
                var x = new System.Xml.Serialization.XmlSerializer(player.GetType());
                player = (Player)x.Deserialize(reader);
            }
            return player;
        }


I'm getting an "InvalidOperationException was unhandled : There was an error reflecting type Serial.Player" on line 15 of the last code I gave. I think it has to do with how I'm serializing my two classes, but I can't see what I'm doing wrong. I know it will be a facepalm when someone points out the obvious error.
Was This Post Helpful? 0
  • +
  • -

#7 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6532
  • View blog
  • Posts: 14,447
  • Joined: 02-June 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 09:00 AM

View PostRobin19, on 15 September 2010 - 07:12 AM, said:

I have a question/problem that relates to tlhIn'toq's answer.

This is all in testing, I just wanted to learn this code for future use. I was able to get it to run beautifully using a simple serialized class. I then wanted to use a class inside a class to create a more complex XML file structure. (Simple Properties and Constructors cut out):

<code clipped for brevity>

I'm getting an "InvalidOperationException was unhandled : There was an error reflecting type Serial.Player" on line 15 of the last code I gave. I think it has to do with how I'm serializing my two classes, but I can't see what I'm doing wrong. I know it will be a facepalm when someone points out the obvious error.


I'm fairly new to serialization myself. I'm learning on the fly.
A) If you create a [Default = something] take on a property that will frak with the serialization.
B) I'm pretty sure you have to have a parameterless constructor in the class or you get an error. Even if you don't use it.
C) [Serializable] I've not tried it as [Serializable()] like a method call.

I did think it odd in your code that you have an entire class for Save. Personally I would just make this a method inside the Score class. That way the ScoreObj understands how to save itself. Then you can make 10 different ScoreObj's (one per player) and tell each one to save itself. Less for you to keep track of.

Later when you make upgrades to the game you can have a PlayerObj with a property of ScoreObj. Each player has their own score than knows how to save itself.

PlayerObj  Tim = new PlayerObj(); // Will init its own score
...

Tim.Score.Save();

Was This Post Helpful? 1
  • +
  • -

#8 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5103
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 09:14 AM

View PosttlhIn, on 15 September 2010 - 03:00 PM, said:

I'm fairly new to serialization myself. I'm learning on the fly.
A) If you create a [Default = something] take on a property that will frak with the serialization.
B) I'm pretty sure you have to have a parameterless constructor in the class or you get an error. Even if you don't use it.
C) [Serializable] I've not tried it as [Serializable()] like a method call.



Gotta love the accidental emoticon bullet point there.

Anyway, there isn't a difference between [Serializable] and [Serializable()]. The parenthesis is for parameters. An empty set of parenthesis should be the same as not providing them at all.
Was This Post Helpful? 1
  • +
  • -

#9 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6532
  • View blog
  • Posts: 14,447
  • Joined: 02-June 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 09:21 AM

View PostinsertAlias, on 15 September 2010 - 08:14 AM, said:

Anyway, there isn't a difference between [Serializable] and [Serializable()]. The parenthesis is for parameters. An empty set of parenthesis should be the same as not providing them at all.


With a method definition I agree. I'm not sure about tags.
Was This Post Helpful? 0
  • +
  • -

#10 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5103
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 09:28 AM

They're the same thing. Think about it more like a constructor than a method call. Here's the MSDN on the SerializableAttribute, they use the ().
http://msdn.microsof...eattribute.aspx

And here's an MSDN article where they mention the same thing, but use it without:
http://msdn.microsof...y/z0w1kczw.aspx

This post has been edited by insertAlias: 15 September 2010 - 09:30 AM

Was This Post Helpful? 2
  • +
  • -

#11 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7163
  • View blog
  • Posts: 14,929
  • Joined: 16-October 07

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 09:56 AM

View PosttlhIn, on 14 September 2010 - 05:22 PM, said:

I'm really lazy. Id make the score a serializable object and let the framework handle the details.


Your example would have me putting Linq in my assembly, which I'd always rather avoid.

It also loads the whole document, at which point I'd just use a document.

Given the XML offered:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filename);
string score = xmlDoc.SelectSingleNode("Score/score").InnerText;


Was This Post Helpful? 1
  • +
  • -

#12 Robin19   User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Loading a single value from XML file in C#

Posted 15 September 2010 - 10:02 AM

View PosttlhIn, on 15 September 2010 - 09:00 AM, said:

B) I'm pretty sure you have to have a parameterless constructor in the class or you get an error. Even if you don't use it.

:oops: That was it. Save didn't have a parameterless constructor. It works fine once you give it one.

Quote

C) [Serializable] I've not tried it as [Serializable()] like a method call.

I was following a serialization how to. I didn't know you could have it without parenthesis. That's good to know.

Quote

I did think it odd in your code that you have an entire class for Save...

I also think it's a bad use of classes. That was why I said it was just a test. I just couldn't think of something better to test the fly. I would never have it structured this way for an actual project.
Was This Post Helpful? 0
  • +
  • -

#13 SHD013   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 33
  • Joined: 30-August 09

Re: Loading a single value from XML file in C#

Posted 16 September 2010 - 05:37 AM

View PostxZachtmx, on 14 September 2010 - 03:10 PM, said:

Hey guys! I am using the XNA game studio for a simple game (I am still learning). So i want to store a high score in an xml file (that seems the easiest for now).

So I made a class called storage with a saveScore and loadScore function. I got the code for savescore working:
        public void saveScore(int score)
        {
            XmlWriterSettings appearance = new XmlWriterSettings();
            appearance.Indent = true;
            XmlWriter xml = XmlWriter.Create(AppDomain.CurrentDomain.BaseDirectory + "Score.xml", appearance);

            xml.WriteStartDocument();
            xml.WriteStartElement("Score");
          
            xml.WriteElementString("score", score.ToString());

            xml.WriteEndElement();
            xml.WriteEndDocument();
            xml.Flush();
            xml.Close();
        }


so if i did storage.saveScore(666);

the score.xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Score>
  <score>666</score>
</Score>



The only thing i am having trouble with is loading the <score> tag back into the game as in int so if i called storage.loadGame(); it would return 666 as an integer.

Can anyone help?

Thanks!
Zach


the loadGame() method is as shown ....
// create an xml document
System.Xml.XmlDocument xSource = new XmlDocument();

// open the file stream where Sfname is the name of the score.xml file..U can use the XML reader class //or simply load the file into the xmlDocument
FileStream fso = new FileStream(Sfname, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

// load the file stream into the document (the program memory)
xSource.Load(fso);

// close the fso because u are only reading it (works for writing also)
fso.Close();

//Declare a node of the XML file (not necessary..unless u want to use the node somewhere else.)
System.Xml.XmlNode NodeSource;

NodeSource = xSource.DocumentElement; // point to the root element...

string score = NodeSource.FirstChild.InnerText;// retrieve the score in string ..

// parse the string score into the Integer form and then use it ..
int Score = int.Parse(score);




Enjoy ...

Note: the xml document comes handy when you are performing various operations on xml (multiple) files ..
Was This Post Helpful? 0
  • +
  • -

#14 Core   User is offline

  • using System.Linq;
  • member icon

Reputation: 782
  • View blog
  • Posts: 5,101
  • Joined: 08-December 08

Re: Loading a single value from XML file in C#

Posted 16 September 2010 - 03:58 PM

View Postbaavgai, on 15 September 2010 - 05:56 PM, said:

Your example would have me putting Linq in my assembly, which I'd always rather avoid.


And what's wrong with using LINQ?
Was This Post Helpful? 0
  • +
  • -

#15 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7163
  • View blog
  • Posts: 14,929
  • Joined: 16-October 07

Re: Loading a single value from XML file in C#

Posted 16 September 2010 - 05:10 PM

LINQ is unnecessary. It's what happens when a C# architect has Ruby envy, or something.

More fundamentally, it's at odds with basic C# object oriented sensibility. Dynamic typed atypical functional style syntax.

Chocolate is nice; wonderful even. On steak, not so much.

This post has been edited by baavgai: 16 September 2010 - 05:10 PM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2