Click here to Skip to main content
15,891,951 members
Articles / Desktop Programming / XAML
Tip/Trick

Easy to Use XML-Writer Class C#

Rate me:
Please Sign up or sign in to vote.
4.08/5 (6 votes)
26 Nov 2013GPL32 min read 33.4K   652   10   2
This is an easy to use class that will help you in creating and reading XMLfiles.

Introduction

By using my XamLister class, you will be able to easily create and read custom XmlFiles, no matter how big they are.

Background

I've been programming in C# since August 2013 and found myself writing the same methods (XmlWrite() and XmlLoad()) again and again.

One day, I learned how to create my own classes and decided to write a few classes that will lighten my workload.

Using the Code

My class consists of only two methods, Write() and Read().

The Write() method needs two lists, two strings, and an XmlWriterSettings object to work properly.

Write(List of Nodes, List of Content (same Order!), Destination Path as string, 
Start Element as String, XmlWriterSettings xms)

It is important that both Lists are in the same order, like this:

Nodelist: (Name (0), Surname(1), Address(3))  Contentlist: (Mark (0), Saltberg(1), San Diego(3)) 

The first Item in the Nodelist will be allocated to the first Item in the Contentlist, etc.

The return value will be a Tuple containing a:

  • Boolean (true, if the writing process was successful and false if it was not)
  • string ("Success" if everything went fine, but containing the Exception if not)

If you do not know how to work with a Tuple, take this as an example:

For example, our Xamlister object is called xlist.

First, you'll need to define an empty variable:

C#
var emptyvar 

Now you can put the return values of xlist.Write() into this variable.

C#
var emptyvar = xlist.Write()

and you can read out both items in emptyvar like this:

C#
bool result = emptyvar.Item1;
string Resultstring = emptyvar.Item2;

The second method is the Read(string Source) method.

This one is very easy, you call it with the Source-XML file you want to read the elements from, the return value is also a Tuple, but this one contains a boolean (true for success and false for failure) and a List of Strings, these are the Element contents of the XML file.

The first element in the list is Startelement, an EndElement is not included.

Reading the values out of this Tuple is as easy as in the first method:

C#
bool result = emptyvar.Item1;
List<string> ResultList = emptyvar.Item2;

 public Tuple<bool, string> Write(List<string> Nodelist, 
 List<string> Contentlist, string Dest, string Startelement, 
 XmlWriterSettings xms)
        {
            try
            {
                if (Contentlist.Count != Nodelist.Count)
                {
                    return Tuple.Create<bool, string>
                    (false, "Your Nodelist does not match the Contentlist!");
                }
                XmlWriter wr = XmlWriter.Create(Dest, xms);
               

                int x = Nodelist.Count;
                int i = 0;

                wr.WriteStartElement(Startelement);
                while (i <= x-1)
                {
                    wr.WriteElementString(Nodelist.ElementAt(i), Contentlist.ElementAt(i));
                    i++;
                }
                wr.WriteEndElement();
                wr.Close();
               
                return Tuple.Create<bool, string>(true, "Success");
            }
            catch (Exception ex)
            {
                return Tuple.Create<bool, string>(false, ex.ToString());
               
            }
        }
C#
public Tuple<bool, List<string>> Read(string Source)
   {

       List<string> Contentlist = null;
       bool Success = false;
       try
       {


           XmlReader re = XmlReader.Create(Source);
           if (re.Read() == true)
           {
               re.ReadStartElement();
           }
           while (re.Read())
           {
               try
               {
                   Contentlist.Add(re.ReadContentAsString());
               }
               catch (Exception ext) //################# Could not find
                           // a way for better error handling
               {
                   try
                   {
                       Contentlist.Add(re.ReadElementContentAsString());
                   }
                   catch (Exception ext2)
                   {
                       Contentlist.Add(re.ReadString());
                   }
               }
           }
           re.Close();
           Success = true;


           return Tuple.Create(Success, Contentlist);
       }
       catch (Exception ex)
       {
           Success = false;
           Contentlist.Add(ex.ToString());

           return Tuple.Create(Success, Contentlist);
       }
   }
C#
       public Tuple<bool, string> Write(List<string> 
Nodelist, List<string> Contentlist, string Dest, string Startelement)
        {
            try
            {
                if (Contentlist.Count != Nodelist.Count)
                {
                    return Tuple.Create<bool, string>
                    (false, "Your Nodelist does not match the Contentlist!");
                }
                XmlWriterSettings xms = new XmlWriterSettings();
                xms.Indent = true;
                xms.NewLineOnAttributes = true;

                XmlWriter wr = XmlWriter.Create(Dest, xms);


                int x = Nodelist.Count;
                int i = 0;

                wr.WriteStartElement(Startelement);
                while (i <= x - 1)
                {
                    wr.WriteElementString(Nodelist.ElementAt(i), Contentlist.ElementAt(i));
                    i++;
                }
                wr.WriteEndElement();
                wr.Close();

                return Tuple.Create<bool, string>(true, "Success");
            }
            catch (Exception ex)
            {
                return Tuple.Create<bool, string>(false, ex.ToString());

            }
        } 
} 

Points of Interest

This class is compatible with nearly every XML file, but it's important that you know the order of the elements you are writing the content to or reading from.

History

  • V 0.1 - 26.11.2013
  • V 0.2 - 29.11.2013

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Student Student
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerProblems with the architecture Pin
Feverbird28-Nov-13 5:35
professionalFeverbird28-Nov-13 5:35 
General[My vote of 2] Some issues with the architecture Pin
John Brett26-Nov-13 22:20
John Brett26-Nov-13 22:20 
First off, writing helper classes for stuff you're doing repeatedly is good for practice, and often good practice if you've first checked whether someone else has already solved the problem.

The comment for the xms parameter of the Write method says
You NEED to put a XmlWriterSettings Item in here

For good reason - the code will throw an exception if you do pass in null, as you simply attempt to set properties on the variable you have just identified as being null.
Quote:
if (xms == null)
{
xms.Indent = true;
xms.NewLineOnAttributes = true;
}


If you're going to allow a default, better to explicitly instantiate a static field/property with appropriate settings, and declare the xms parameter to have a default value of said default property e.g.
C#
public static XmlWriterSettings DefaultWriterSettings{get;}
public Tuple<bool, string> Write(List<string> Nodelist, List<string> Contentlist, string Dest, string Startelement, XmlWriterSettings xms= Xamlister.DefaultWriterSettings)

Alternatively, simply throw an ArgumentNullException if the value is not passed in and require the caller to supply the structure.

Requiring the caller to supply two lists that are exactly in step is usually a sign of inappropriate data structures. I'm not sure what you're trying to achieve with this, so I can't suggest a solution, but generally you'd want one data structure that referenced both meta-data (the element names) and the data itself (the content). There are many ways of achieving this, depending upon the situation. Not being able to use Enumeration syntax (e.g. foreach) is a warning sign here, IMHO.

Having placed this restriction upon the caller, the code doesn't check for the condition, leaving the runtime to throw an IndexOutOfRangeException if the Nodelist is too long, or silently ignoring the issue if the Contentlist is longer than expected (ouch).

Having the Write code handle exceptions, and translate them into a complex return value (a tuple in which the interpretation of Item2 depends upon the value of Item1) is not, IMHO, helpful. The general rule with catching exceptions is to do so when you can add value to the code. The current implementation complicates error handling, rather than simplifying it. I would have preferred the code to not catch exceptions at all, and have a void return.

I'm not comfortable with the behaviour of the Read code with respect to elements and content. Catching any exception and simply trying a different way of fetching the data is poor practice (what if the error were one unrelated to using ReadContentAsString on an element?).
C#
try
{
    Contentlist.Add(re.ReadContentAsString());
}
catch (Exception)
{
    Contentlist.Add(e.ReadElementContentAsString());
}


Despite putting strict requirements upon the Write method to ensure that the Nodelist and Contentlist line up, there's no validation at all on the read to ensure that the expected elements are present in the order expected.

John

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.