views:

72

answers:

4

Heya all,

I was wondering what your opinion about this would be. I'm trying to convert an xml file to a .net object. It's a xml file from the World of Warcraft armory. Here is an example.

<?xml version="1.0" encoding="UTF-8"?>
<baseStats>
<strength attack="48" base="48" block="-1" effective="58"/>
 <agility armor="114" attack="-1" base="47" critHitPercent="4.27" effective="57"/>
 <stamina base="70" effective="1186" health="11680" petBonus="-1"/>
 <intellect base="198" critHitPercent="10.41" effective="1529" mana="22655" petBonus="-1"/>
 <spirit base="190" effective="770" healthRegen="39" manaRegen="503"/>
 <armor base="2150" effective="2150" percent="12.37" petBonus="-1"/>
</baseStats>

I've thought of 2 ways to convert this to an object and I'd like to hear your opinion about it. Ill show them.

class BaseStats{
 public int StrengthAttack{get;set;}
 public int StrengthBase{get;set;}
 public int StrengthBlock{get;set;}
 ...
 public int ArmorBase{get;set;}
 public int ArmorEffective{get;set;}
 ...
}

or

class BaseStats{
 public Strength Strength{get;set;}
 public Armor Armor{get;set;}

 public class Strength{
  public int Attack{get;set;}
  public int Base{get;set;}
  public int Block{get;set;}
 }

 public class Armor{
  public int Base{get;set;}
  public int Effective{get;set;}
 }
}

Do you see what I'm trying here. What would be your opinion about each of those ways. Or can you think of any others?

+1  A: 
class CElement
{
    public int? attack { get; set; }
    public int? base { get; set; }
    public int? block { get; set; }
    public int? effective { get; set; }
    public int? petBonus { get; set; }
    public int? mana { get; set; }
    public int? healthRegen { get; set; }
    public int? manaRegen { get; set; }

    public double? critHitPercent { get; set; }
    public double? percent { get; set; }
}

class CBaseStats
{
    public CElement strength;
    public CElement agility;
    public CElement stamina;
    public CElement intellect;
    public CElement spirit;
    public CElement armor;
}
Svisstack
Yup this seems like a good way to do it. But however, what I don't really seem to like about it is that CElement strength doesn't use all of the properties it has. It seems kinda strange to do it this way. I can be nitpicking though xD
Timo Willemsen
@Timo Willemsen: If attribute dont exists then you leave her value as NULL, for it i used int? and double? declaration insead of int and double
Svisstack
Yup that's true. Only the class I'm trying to created is gonna be in a library I'm writing. To keep it as clean as possible and to avoid confusing (since other people are using it, ideally) I'm trying to avoid these things.
Timo Willemsen
@Timo Willemsen: ahh, then you must do good design call, i only answer on your question and i dont know what you want achieve
Svisstack
+2  A: 

If you have the XSD schema (or can create one), I've used LinqToXsd to create some quick objects. The nice thing about LinqToXsd is that it creates methods you can use to easily parse XML into your objects.

Microsoft has released it as Open Source - and you can simply use a command-line call to pass in your .xsd and it will generate a .cs file with all of your classes.

bporter
That seems nice but unfortunately I don't have access to the XSD scheme. I bookmarked it though, it seems real useful.
Timo Willemsen
I understand. However, you may consider if it's easier to handwrite all of the code (declarations, gets, sets, constructors, parsers, etc.), or handwrite a small XSD that matches the schema. If you write the XSD, you can easily autogenerate your .NET code and parsing logic again. Just a thought. Good luck! :)
bporter
True true, but the example I gave was just a very small part of the actual XML file. The actual XML file is roughly 200 times bigger :P
Timo Willemsen
+3  A: 

Classless Design using an Anonymous Type

Here's another way, with .NET 3.5, if you don't want to design an explicit class you can build the object dynamically as an anonymous type; one caveat being the object properties are read-only after being initialized.

Use the XML LINQ classes to query the XML content with.

using System;
using System.IO;
using System.Xml.Linq;

Load up the XML string and query it to create an object.

// 1. Load your string into a document.
XDocument xdoc = XDocument.Load(new StringReader(my_WoW_XML_String));

// 2. Create the anonymous type...
var statsObject = new
{
    StrengthInfo = new
    {
        Attack = int.Parse(xdoc.Element("strength").Element("attack").Value),
        Base = int.Parse(xdoc.Element("strength").Element("base").Value),
        Block = int.Parse(xdoc.Element("strength").Element("block").Value),
        Effective = int.Parse(xdoc.Element("strength").Element("effective").Value),
    },

    AgilityInfo = new
    {
        Armor = int.Parse(xdoc.Element("agility").Element("armor").Value),
        Attack = int.Parse(xdoc.Element("agility").Element("attack").Value),
        Base = int.Parse(xdoc.Element("agility").Element("base").Value),
        CritHitPercent = int.Parse(xdoc.Element("agility").Element("critHitPercent").Value),
        Effective = int.Parse(xdoc.Element("agility").Element("effective").Value),
    }

    // Do the same with <spirit> and <armor> elements, etc.
    // Include only the properties you want from the XML. 

}; // end anonymous object.

Use your anonymous object normally like so:

Console.Write("strength: attack={0}, effective={1}; armor agility={2}", 
    statsObject.StrengthInfo.Attack,
    statsObject.StrengthInfo.Effective,
    statsObject.AgilityInfo.Armor);

// Do whatever you want with the object version of WoW stats.

If you have multiple XML files to process with the same schema then just wrap all the above in a loop to process one at a time.

John K
A: 

If you got complete xml, 1. generate xsd from xml using the xsd.exe tool 2. generate class from the generated xsd using xsd.exe tool

http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx

geeth