none
Create, Modify and Read XML Files in C# RRS feed

  • Question

  • Hey peeps,

    I have created my own wizard that uses a XML file to store user input. First off, I have no clue where to start or what to do. If there is someone out there that can provide me with a code sample or point me to some sort of code sample that will show me how to read, write and modify XML files from C#.

    Thanks in advance.

    Friday, November 11, 2011 12:09 PM

All replies

  • what do you use for creating application: WinForms or WPF or ASP.NET or ASP.NET MVC?
    • Edited by Malobukv Friday, November 11, 2011 12:29 PM
    Friday, November 11, 2011 12:28 PM
  • Hey Malobukv,

    It's for a WinForms application. What I need to do is create the XML file containing the first pages' values, if the user cancels, exits or continues, the data is stored temporarily in a XML file. On the next page of the wizard, that pages' values needs to be appended to the rest of the document, and so forth. If, by any chance, the user cancel and continues at a later stage, I need to provide them with the values they have provided earlier and be able to modify those values. Once they have completed the wizard, I will read the file and insert all values directly to SQL.

    Any good examples around?

    Friday, November 11, 2011 12:36 PM
  • The .NET framework has lots of options to work with XML, one is LINQ to XML , another is XML serialization, which by now comes in two versions, DataContractSerializer and XmlSerializer.
    MVP Data Platform Development My blog
    Friday, November 11, 2011 12:54 PM
  • Any good examples around?

    Hi,

    Here a small example that uses the XmlSerializer to write data from a class into an Xml and reads it back:

    using System;
    using System.Xml.Serialization;
    using System.IO;
    
    namespace XmlDataSerializer
    {
        // The data class containing two properties 
        [Serializable()]
        public class Data
        {
            public String FirstProperty { get; set; }
            public int SecondProperty { get; set; }
        }
    
    
        // The test program
        class Program
        {
    
            static void Main(string[] args)
            {
    
                Data tx = new Data();
                tx.FirstProperty = "Hello Word";
                tx.SecondProperty = 4711;
    
                // Write to XML
                XmlSerializer writer = new XmlSerializer(typeof(Data));
                using (FileStream file = File.OpenWrite("data.xml"))
                {
                    writer.Serialize(file, tx);
                }
    
                // Read from XML
                Data rx;
    
                XmlSerializer reader = new XmlSerializer(typeof(Data));
                using (FileStream input = File.OpenRead("data.xml"))
                {
                    rx = reader.Deserialize(input) as Data;
                }
    
                Console.WriteLine("1st = <{0}, 2nd = <{1}>", rx.FirstProperty, rx.SecondProperty);
                Console.ReadLine();
    
    
    
            }
        }
    }
    
    


    The XML looks like that:

    <?xml version="1.0"?>
    <Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <FirstProperty>Hello Word</FirstProperty>
      <SecondProperty>4711</SecondProperty>
    </Data>
    


    This approach is quite easy and you do not have to change the part for writing and reading the XML when you extend your data set by some additional properties

    Cheers,

    Stefan

     

    • Proposed as answer by Hubery Yuan Monday, December 19, 2011 6:40 AM
    Friday, November 11, 2011 8:47 PM
  • > It's for a WinForms application. What I need to do is create the XML file [...] If, by any chance, the user cancel and continues at a later stage, I need to provide them with the values they have provided earlier and be able to modify those values.

     

    take a look at my examples here.
    below is another one with different type of bindings.

       
    using System;
    using System.Data;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication0
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                this.Size = new System.Drawing.Size(600, 600);
                var ds = new DataSet();
                ds.ReadXml(new StringReader(@"
                    <wizard>
                        <pages current-page='1'>
                            <page id='1'>
                                <address id='1'>address 1</address>
                                <type text='type 1'>true</type>
                                <type text='type 2'>true</type>
                                <type text='type 3'>true</type>
                                <match text='m 1' value='true' />
                                <match text='m 2' />
                                <match text='m 3' />
                            </page>
                            <page id='2'>
                                <address id='2'>address 2</address>
                                <item value='v1'>txt</item>
                                <item value='v2' />
                                <item value='v3' />
                            </page>
                        </pages>
                    </wizard>"));
                // pages
                var tc = new TabControl { Parent = this, Dock = DockStyle.Fill };
                CreatePage1(ds, new TabPage { Parent = tc, Padding = new Padding(5) });
                CreatePage2(ds, new TabPage { Parent = tc, Padding = new Padding(5) });
                // navigator
                var p = new Panel { Parent = this, Dock = DockStyle.Bottom, Height = 30, Padding = new Padding(0, 0, 100, 5) };
                new Button { Parent = p, Dock = DockStyle.Right, Text = "Prev", Width = 100 }
                    .Click += (s, e) => tc.SelectTab(0);
                new Button { Parent = p, Dock = DockStyle.Right, Text = "Next", Width = 100 }
                    .Click += (s, e) => tc.SelectTab(1);
                // xml view
                var trace = new RichTextBox { Parent = this, Dock = DockStyle.Bottom, Height = 250, ReadOnly = true };
                foreach (DataTable dt in ds.Tables)
                    dt.ColumnChanged += (s, e) => trace.Text = ds.GetXml();
    
                tc.DataBindings.Add("SelectedIndex", ds, "pages.current-page");
            }
            void BindTextBox(object ds, string dm, TextBoxBase tb)
            {
                var b = tb.DataBindings.Add("Text", ds, dm);
                tb.TextChanged += (s, e) =>
                {
                    var ss = tb.SelectionStart;
                    b.WriteValue();
                    tb.SelectionStart = ss;
                };
            }
            private void CreatePage1(DataSet ds, Control parent)
            {
                var dv = new DataView { Table = ds.Tables["page"], RowFilter = "id=1" };
                BindTextBox(dv, "page_address.address_text",
                    new RichTextBox { Parent = parent, Dock = DockStyle.Bottom, Height = 150 });
                var types = dv[0].Row.GetChildRows("page_type");
                var p1 = new Panel {Dock = DockStyle.Left, Width = 100 };
                for (var i=0; i < types.Length; i++)
                {
                    var row = types[i];
                    var cb = new CheckBox { Parent = p1, Dock = DockStyle.Top, Text = row["text"].ToString() };
                    cb.CheckedChanged += (s, e) =>
                        row["type_text"] = (s as CheckBox).Checked;
                }
                var matches = dv[0].Row.GetChildRows("page_match");
                var p2 = new Panel {Dock = DockStyle.Left, Width = 100 };
                for (var i=0; i < matches.Length; i++)
                {
                    var row = matches[i];
                    var rb = new RadioButton { Parent = p2, Dock = DockStyle.Top, Text = row["text"].ToString(), 
                        Checked = (row["value"] is DBNull) ? false : bool.Parse(row["value"] as string) };
                    rb.CheckedChanged += (s, e) =>
                        row["value"] = (s as RadioButton).Checked;
                }
                new Panel { Dock = DockStyle.Fill, Parent = parent }.Controls.AddRange(new [] { p1, p2 });
            }
            private void CreatePage2(DataSet ds, Control parent)
            {
                var dv = new DataView { Table = ds.Tables["page"], RowFilter = "id=2" };
                BindTextBox(dv, "page_address.address_text",
                    new RichTextBox { Parent = parent, Dock = DockStyle.Fill });
                var dv2 = new DataView { Table = ds.Tables["item"], RowFilter = "parent(page_item).id=2" };
                new DataGridView
                {
                    Parent = parent,
                    DataSource = dv2,
                    Dock = DockStyle.Right,
                    AllowUserToAddRows = false,
                    AllowUserToDeleteRows = false,
                    Width = 400
                };
            }
            class TabControl : System.Windows.Forms.TabControl
            {
                protected override void WndProc(ref Message m)
                {
                    // hide tabs
                    if (m.Msg == 0x1328)     // TCM_ADJUSTRECT
                        m.Result = (IntPtr)1;
                    else
                        base.WndProc(ref m);
                }
            }
        }
    }
    
    


    Friday, November 11, 2011 9:40 PM
  • Here is an example with LinqToXML:

    using System;
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    
    namespace LinqToXML
    {
        internal class UserInput
        {
            public string UserId { get; set; }
            public string Input { get; set; }
        }
    
    
        internal class Program
        {
            private static void Main()
            {
                // define the XML file path
                const string xmlpath = @"..\..\inputs.xml";
    
                // Create some data
                var ui = new[]
                             {
                                 new UserInput {UserId = "1245", Input = "1$"},
                                 new UserInput {UserId = "1235", Input = "10$"},
                                 new UserInput {UserId = "1545", Input = "100$"},
                                 new UserInput {UserId = "1295", Input = "1000$"},
                                 new UserInput {UserId = "1265", Input = "10000$"},
                                 new UserInput {UserId = "1945", Input = "100000$"}
                             };
    
                // Create the XML file if it does not exist
                if (!File.Exists(xmlpath)) File.WriteAllText(xmlpath, "<userInputs />");
    
                // Load the XML document
                XDocument xd = XDocument.Load(xmlpath);
    
                // Write data
                if (xd.Root != null)
                    foreach (UserInput i in ui)
                        xd.Root.Add(new XElement("userInput", new XAttribute("UserId", i.UserId),
                                                 new XAttribute("Input", i.Input)));
    
                // Modify data
                XElement firstOrDefault = xd.Descendants("userInput").Where(e =>
                                                                                {
                                                                                    XAttribute xAttribute =
                                                                                        e.Attribute("UserId");
                                                                                    return xAttribute != null &&
                                                                                           xAttribute.Value == ui[0].UserId;
                                                                                }).FirstOrDefault();
                if (firstOrDefault != null)
                {
                    XAttribute attribute = firstOrDefault.Attribute("Input");
                    if (attribute != null)
                        attribute.Value = "0.99$";
                }
    
                // Delete data
                xd.Descendants("userInput").Where(e =>
                                                      {
                                                          XAttribute xAttribute = e.Attribute("UserId");
                                                          return xAttribute != null && xAttribute.Value == ui[1].UserId;
                                                      }).First().Remove();
    
                // Search data
                XAttribute xAttribute1 = xd.Descendants("userInput").Where(e =>
                                                                               {
                                                                                   XAttribute xAttribute =
                                                                                       e.Attribute("UserId");
                                                                                   return xAttribute != null &&
                                                                                          xAttribute.Value == ui[3].UserId;
                                                                               }).First().Attribute("Input");
                if (xAttribute1 != null) Console.WriteLine("User3 Input: {0}", xAttribute1.Value);
    
                // Save data
                xd.Save(xmlpath);
    
                // Exit
                Console.Write("Press any key to exit ...");
                Console.ReadKey();
            }
        }
    }
    

    Kind regards,


    aelassas.free.fr
    Saturday, November 12, 2011 1:58 AM
  • @Malobukv, why don't you place the controls in the Form.Designer.cs ?

    aelassas.free.fr
    Saturday, November 12, 2011 2:09 AM
  • > why don't you place the controls in the Form.Designer.cs ?


    the code above is just a sample. you are right, in real project the code should be in different files, and even in different assemblies.
    Saturday, November 12, 2011 9:37 AM
  • Hey, Malobukv

                   If I used linqtoXml to create and save the xml file, can I use fileinfo attribution to hide the created XML file? I got problem when I try to reload the xml and edit.  PS: Can I use XmlSerializer and LinqtoXML in the same project?

    Monday, November 21, 2011 9:47 AM
  • It is certainly technically possible to use LINQ to XML and XmlSerializer in the same project, it is however questionable whether it is needed.
    MVP Data Platform Development My blog
    Monday, November 21, 2011 10:35 AM