Sign in to follow this  
GameMasterXL

Reading XML using C#

Recommended Posts

GameMasterXL    100
I have searched everywere and havn't found much good info on this. Is what i am wanting to do is read in a xml file that will store how my program looks like the background colour, font colour, font size, font type, font style ect ect so then i could change the programs looks with xml. This is what a basic xml file for my program would look like:
<buttons>
 <bgcolor>red</bgcolor>
 <fontcolor>blue</fontcolor>
 <fontsize>12</fontsize>
 <fonttype>arial</fonttype>
 <fontstyle>bold</fontstyle>
</buttons>

How would i read this in so i can get each individual value to change my programs properties and be able to allways expand on the xml file aswell? thanks in advance. [/source]

Share this post


Link to post
Share on other sites
GameMasterXL    100
Quote:
Original post by Dave Hunt
There are a ton of XML-with-C# articles here.


I did find one usefull there but it only seemed to read in all commands like this
<width> .. </width>
<height> .. </height>

and i don't think i can encapsulate the attributes into each object like in my xml setup file i want to be able to change buttons ui, textboxs, window, font ect and each one of those are in its own catogary with its own attributes like
<buttons>
<width>123</width>
</buttons>


I will also look into serialization to but i suck at xml lol.

Share this post


Link to post
Share on other sites
Dave Hunt    4872
You might try a format more like this:

<buttons>
<property name="bgcolor" value="red" />
<property name="fontcolor" value="blue />
<property name="fontsize" value="12" />
<property name="fonttype" value="arial" />
<property name="fontstyle" value="bold" />
</buttons>

I find that a bit easier to parse.

Share this post


Link to post
Share on other sites
Rob Loach    1504
You have a couple of options when it comes to XML in .NET:

  • The System.Xml namespace provides a XmlDocument which you can use to construct and "destruct" XML documents. You pretty much just write it node by node or read through it node by node.
  • The IXmlSerializable interface will let you serialize classes by reading and writing the members your own way.
  • With the XmlSerializer class, you can serialize classes to xml dynamically.

Play around with each method of creating and reading XML data and pick which method you like best. It really depends on what you're trying to accomplish with what you're doing.

Share this post


Link to post
Share on other sites
GameMasterXL    100
Is what i am creating is a setup file so i can read the xml data in and each element has attributes then i read each attribute in and assigne the value of each into the right variable. How can i do this can you by anychance show some code? thanks.

Share this post


Link to post
Share on other sites
xycos    146
Here's some code from my game. Obviously, it has nothing to do with whatever you're doing, but you might be able to gleam something from it.

    public static void loadShipsXml() {

SHIPS = new Dictionary<string, ShipData>();

XmlDocument doc = new XmlDocument();
doc.Load(Settings.DATA_PATH + @"ships.xml");
XmlNode rootNode = doc.DocumentElement;
XmlNodeList allShips = rootNode.ChildNodes;
for(int i = 0; i < allShips.Count; i++) {
ShipData nextShip = new ShipData();
XmlElement current = (XmlElement) allShips[i];
XmlNodeList children = current.ChildNodes;
for(int j = 0; j < children.Count; j++) {
if(children[j].Name == "speed") {
nextShip.speed = double.Parse(children[j].InnerText);
} else if(children[j].Name == "hp") {
nextShip.hp = int.Parse(children[j].InnerText);
} else if(children[j].Name == "graphics") {
nextShip.graphics = Settings.processXMLGraphics(children[j]);
} else if(children[j].Name == "component") {
nextShip.components.AddLast(ComponentData.COMPONENTS[children[j].InnerText]);
}
}
SHIPS.Add(current.Attributes[0].Value, nextShip);
}

Share this post


Link to post
Share on other sites
SnprBoB86    277
Side note:

C# allows switches on strings:


if(children[j].Name == "speed") {
nextShip.speed = double.Parse(children[j].InnerText);
} else if(children[j].Name == "hp") {
nextShip.hp = int.Parse(children[j].InnerText);
} else if(children[j].Name == "graphics") {
nextShip.graphics = Settings.processXMLGraphics(children[j]);
} else if(children[j].Name == "component") {
nextShip.components.AddLast(ComponentData.COMPONENTS[children[j].InnerText]);
}




can become:


switch (children[j].Name)
{
case "speed":
nextShip.speed = double.Parse(children[j].InnerText);
break;
case "hp":
nextShip.hp = int.Parse(children[j].InnerText);
break;
case "graphics"
nextShip.graphics = Settings.processXMLGraphics(children[j]);
break;
case "component":
nextShip.components.AddLast(ComponentData.COMPONENTS[children[j].InnerText]);
break;
}


Share this post


Link to post
Share on other sites
joanusdmentia    1060
IMHO serialization will be the simplest approach for this.


using System.Drawing;
using System.Xml.Serialization;

[Serializable]
class Buttons
{
public KnownColor BgColor;
public KnownColor FontColor;
public int FontSize;
public string FontName;
public FontStyle FontStyle;

public static Buttons Load(Stream stream)
{
XmlSerializer serializer = new XmlSerializer(typeof(Buttons));
return (Buttons)serializer.Deserialize(stream);
}
}





A whooping 2 lines of code to load your settings from an already open stream. KnownColor is an enumeration of known color names, if you don't want this you can just use a string instead. Similarly for Fontstyle.

See here for info on attributes that let you do all sorts of stuff (change the name of nodes so that they don't have to match the variable names, use XML attributes instead of nodes, etc.).

Share this post


Link to post
Share on other sites
GameMasterXL    100
It seems though that the serializer just writes data out. This is what i am wanting to parse this type of data and the way it is layed out can change.


<buttons>
<property: name="bgcolor" value="red"/>
<property: name="bdcolor" value="blue"/>
<property: name="font" value="arial"/>
<property: name="fontcolor" value="white"/>
</buttons>
<mainapp>
<property: name="appico" value="default.ico"/>
<property: name="bgcolor" value="darkblue"/>
</mainapp>



So it would contain attributes like the above, i am a bit confused still on how i would parse this in so i can get all the data from each attribute and store it into variables? sorry about the questions i am new at C#.

Share this post


Link to post
Share on other sites
Vexorian    152
With xml it is sometimes a matter of style, I would go with :


<buttons bgcolor="red" bdcolor="blue" font="arial" fontcolor="white"/>
<mainapp appico="default.ico" bgcolor="darkblue"/>



I do things like that myself as much as possible, I kind of dislike to have elements if they only have content and don't have child elements, then I preffer them as attributes as long as the values are to be expected

feeling: This is the kind of format that works better with ini, ouch

[Edited by - Vexorian on November 13, 2005 3:31:05 PM]

Share this post


Link to post
Share on other sites
dalleboy    324
Input test.xml:

<buttons>
<bgcolor>red</bgcolor>
<fontcolor>blue</fontcolor>
<fontsize>12</fontsize>
<fonttype>arial</fonttype>
<fontstyle>bold</fontstyle>
</buttons>




Program using XPath:

using System;
using System.Xml.XPath;

class Program
{
static void Main()
{
XPathDocument doc = new XPathDocument(@"test.xml");
XPathNavigator nav = doc.CreateNavigator();
Console.WriteLine(nav.SelectSingleNode(@"//bgcolor").Value);
Console.WriteLine(nav.SelectSingleNode(@"//fontcolor").Value);
Console.WriteLine(nav.SelectSingleNode(@"//fontsize").ValueAsInt);
Console.WriteLine(nav.SelectSingleNode(@"//fonttype").Value);
Console.WriteLine(nav.SelectSingleNode(@"//fontstyle").Value);
}
}




Output:

red
blue
12
arial
bold





Learn XPath

Disclaimer: The above XPath strings sent to SelectSingleNode are probably not 100% correct, I do not know XPath.

Share this post


Link to post
Share on other sites
joanusdmentia    1060
Quote:
Original post by GameMasterXL
It seems though that the serializer just writes data out. This is what i am wanting to parse this type of data and the way it is layed out can change.

So it would contain attributes like the above, i am a bit confused still on how i would parse this in so i can get all the data from each attribute and store it into variables? sorry about the questions i am new at C#.


Did you even look at the link I provided? The serializer both serializes (writes) and deserializes (read). Here's an example that will parse your desired structure (ignoring the ':', I'm not sure if that's valid since it's used to specify the namespace).


using System.Drawing;
using System.Xml.Serialization;

[Serializable]
class Property
{
[XmlAttribute("name")] public string Name;
[XmlAttribute("value")] public string Value;
}


[Serializable]
[XmlRoot("rootnodename")]
class Settings
{
[XmlArray("buttons")]
[XmlArrayItem("property")]
public Property[] Buttons;

[XmlArray("mainapp")]
[XmlArrayItem("property")]
public Property[] MainApp;

public static Settings Load(Stream stream)
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
return (Settings)serializer.Deserialize(stream);
}
}






As you can see, the code for loading the settings is exactly the same (apart from the different type being loaded), the way in which the data is structured is control by A) the structure of your types and B) the attributes you apply to their members. If you want to use a Hashtable so that you can index properties by their name things start to get more complicated and a different approach may prove to be easier.

Share this post


Link to post
Share on other sites
Krisc    494
You should also use String.Equals() instead of == for strings.

Quote:
Original post by SnprBoB86
Side note:

C# allows switches on strings:

*** Source Snippet Removed ***

can become:

*** Source Snippet Removed ***


Share this post


Link to post
Share on other sites
Rob Loach    1504
I was working with unmanaged code for one project and needed a way to customize getting and setting the XML elements so that I had full control over the conversion. So I started up a new project and did some tests and came up with a new class named XmlDictionary.

It's pretty much a Hashtable (string-value pairs) that can be saved and loaded as XML. You can store any primitive datatype in it as well as any user class you make that implements IXmlDictionaryElement.


// Save some information as XML
XmlDictionary data = new XmlDictionary("data.xml");
data["Width"] = 640;
data["Height"] = 480;
data["Title"] = "Hello World!";
data.Save();

// Load the data from the disk
XmlDictionary loadedData = new XmlDictionary();
loadedData.Load("data.xml");

// Display some data from it...
System.Console.WriteLine( loadedData["Title"] );
System.Console.WriteLine("Width: " + loadedData["Width"] );
System.Console.WriteLine("Height: " + loadedData["Height"] );

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this