Александр Д.
Александр Д.

Reputation: 1149

Tool that auto-generate a code for accesing a xml-file

My application have a configuration xml-file. That file contains more than 50 program settings. At the present time I read and save each program setting separately. I guess It is not effiсiently for such tasks.

I need something that can auto-generate a code for load and save my program settings using predefined xml-schema.

I found a dataset in Add New Item dialog. Unfortunately, i cannot add new code to dataset1 such as events in set-accessors of properties because of this

//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.

Maybe, there is a tool that allows a user to generate a wrapper for accesing a xml-file ? Such as DataSet1, but with availability to add events.

Edit: I didn't mark a useful answer because i read an articles (link) which you give me. I will mark useful answer later.

Upvotes: 3

Views: 2901

Answers (8)

code4life
code4life

Reputation: 15794

You can follow these steps:

1) generate an XSD file from your XML file. For There used to be a tool to infer schema from an XML file, I forgot what it's called. Currently I use my own utility, which basically runs this core routine to read an xml file and generate the corresponding xsd:

static void InferSchema(string fileName)
{
    XmlWriter writer = null;
    XmlSchemaInference infer = new XmlSchemaInference();
    XmlSchemaSet sc = new XmlSchemaSet();

    string outputXsd = fileName.Replace(".xml", ".xsd");
    sc = infer.InferSchema(new XmlTextReader(fileName));

    using (writer = XmlWriter.Create(new StreamWriter(outputXsd)))   
    {
        foreach(XmlSchema schema in sc.Schemas())
        {
            schema.Write(writer);
            Console.WriteLine(">> found schema - generated to {0}", 
            outputXsd);
        }
    }
}

2) run xsd.exe to generate a serializable class from the XSD file.

xsd.exe /c /n:MyNameSpaceHere MyGenerated.xsd

Next, you can read the XML file into the serializable class using XmlSerializer.Serialize() method. Something like this:

    public static void Serialize<T>(T data, TextWriter writer)
    {
        try
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            xs.Serialize(writer, data);
        }
        catch (Exception e)
        {
            throw;
        }
    }

Finally, you can write back to the XML file from the class using the XmlSerializer.Deserialize() method, like this for instance:

public static void Deserialize<T>(out T data, XmlReader reader)
{
    try
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        data = (T)xs.Deserialize(reader);
    }
    catch (Exception e)
    {
        reader.Close();
        throw;
    }
}

Upvotes: 1

alimbada
alimbada

Reputation: 1401

Why not use a .Settings file?

Upvotes: 1

Pretzel
Pretzel

Reputation: 8291

If you are not willing to use app.config/web.config or the properties file (which Oded and Bruno recommend and I recommend as well), I highly recommend this utility:

Web Services Contract First (WSCF) Blue for VS2008 and VS2010

If you're on VS2005, you'll want this version of the tool: http://www.thinktecture.com/resourcearchive/tools-and-software/wscf (don't use the VS2008 version on this site. I could never get it to work right.)

Once you have the plugin installed into Visual Studio, you'll need an XSD schema of your XML file. (Google for an online XSD Generator.) Following the instructions found on the WSCF website, you can generate a wrapper class that will deserialize and reserialize your XML and give you an abstracted view of your XML.

I figure it is impossible (or at least very hard) to add new node/element TYPES, but adding new instances of existing node/element types, accessing to your data, editing the data, reordering nodes, and then saving back out are all easy.

Deserialization code looks like this:

private MyGeneratedXMLconfigClass config;
using (StreamReader sr = new StreamReader(filename))
{
   XmlSerializer cXml = new XmlSerializer(typeof(MyGeneratedXMLconfigClass));
   config = (MyGeneratedXMLconfigClass)cXml.Deserialize(sr);
}

Now your XML has been de-serialized into the "config" instance of your custom class. Then you can access the whole class as a series of nested values and Lists.

For example:

string errorFile = config.errorsFile;
List<string> actions = config.actionList;
var specialActions = from action in config.actionList
                      where action.contains("special")
                      select action;

Etc., etc. Then once you're done manipulating your data, you can re-serialize with this code:

using (StreamWriter wr = new StreamWriter(filename, false))
{
   XmlSerializer cXml = new XmlSerializer(typeof(MyGeneratedXMLconfigClass));
   cXml.Serialize(wr, config);
}

One of the very nice things about this tool is that it auto-generates all classes as "partial" classes, so that you can feel free to extend each class on your own without fear of your code getting stomped on in case you ever need to re-generate because the XSD/XML was changed.

I imagine this might sound like a lot, but the learning curve is actually pretty easy and once you get it installed and working, you'll realize how stupidly easy it is. It's worth it. I swear. :-)

Upvotes: 3

Luka Ramishvili
Luka Ramishvili

Reputation: 899

You can use System.Xml.Serialization - it's very easy and you can serialize even class objects directly, like MyCustomClass (it even saves MyCustomClass public fields).

Deserializing the XML file will get a new instance of MyCustomClass, so such a feature is priceless.

Note one thing: you should add EVERY SINGLE TYPE you use in the class, but that's easy though.

I attached a complete project that does the thing you want. just change classes and objects and that will be all. source code

for example (i'm shortening the code):

using System.Xml;
using System.Xml.Serialization;
using System.IO;

[XmlRootAttribute("Vendor")]
class Vendor{
    [XmlAttribute]
    Product prod;
}
[XmlRootAttribute("Product")]
class Product{
    [XmlAttribute]
    public string name="";
}

class Test{
    Vendor v=new Vendor();
    Product p=new Product();
    p.name="a cake";
    v.prod=p;

    //add EVERY SINGLE TYPE you use in the serialized class.
    Type[] type_list = { typeof(Product) };

        XmlSerializer packer = new XmlSerializer(v.GetType(),type_list);
        XmlWriter flusher = XmlWriter.Create(@"c:\bak.xml");




        packer.Serialize(flusher, v);

        flusher.Close();

        XmlReader restorer = XmlReader.Create(@"c:\bak.xml");
        Vendor v2 = (Vendor)packer.Deserialize(restorer);

    //v2.prod.name is now "cake"
    //COOL was my first impression :P

}

Upvotes: 0

Daniel Rose
Daniel Rose

Reputation: 17638

If you have an XSD file, you can generate classes from that. Besides the already mentioned xsd.exe from Microsoft (which hasn't been updated for quite some time), there are other tools for this. I am using XSD2Code, which allows generating strongly typed collections, lazy initialization, etc.

If you do not have an XSD, you can point the xsd.exe at your xml-file, and it will generate an XSD from that. The schema usually needs some work, but generally is a good starting point.

xsd.exe (instance).xml

Upvotes: 0

b.roth
b.roth

Reputation: 9532

This is called a properties file. C# should have something similar to Java's Properties class where you can load all properties without hard-coding their names.

EDIT: There's apparently no built-in properties parsing solution for C#. But you can easily implement your own. See here.

Upvotes: 0

Oded
Oded

Reputation: 498914

Why are you using hand rolled XML for configuration? What is wrong with the existing app.config and web.config schemas?

Upvotes: 1

codencandy
codencandy

Reputation: 1721

If you have an appropriate xsd schema for your xml file microsoft provides xsd.exe, a small tool which auto-generates c# classes for this schema.

For details see: http://msdn.microsoft.com/en-us/library/x6c1kb0s%28VS.71%29.aspx

Upvotes: 2

Related Questions