0

I have the following DataTable:

A   B   C
----------
A1  B1  C1
A1  B1  C2
A1  B1  C3
A1  B2  C1
A1  B2  C2
----------

I tried to convert it using C# to be in XML format like this:

<Data>
    <A>
        <lable>A1</lable>
        <B>
            <lable>B1</lable>
            <C>
                <lable>C1</lable>
                <lable>C2</lable>
                <lable>C3</lable>
            </C>
            <lable>B2</lable>
            <C>
                <lable>C1</lable>
                <lable>C2</lable>
            </C>
        </B>
    </A>
</Data>

I did a deep search and I found something helpful online like this. But that one uses relations, and my data is just one table. I also tried this C# code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Xml.Linq;
    using System.Data.SqlClient;

    SqlConnection con = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Files;Data Source=localhost");
    con.Open();
    SqlCommand cmd = new SqlCommand("select * from MyTable",con);
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    DataTable DT = new DataTable("Data");
    da.Fill(DT);
    dataGridView1.DataSource = DT;
    con.Close();
    string XML = ToXmlFormat(DT, 0);
    Console.WriteLine(XML);


public string ToXmlFormat(this DataTable table, int metaIndex = 0)
{
    XDocument xdoc = new XDocument(
        new XElement(table.TableName,
            from column in table.Columns.Cast<DataColumn>()
            where column != table.Columns[metaIndex]
            select new XElement(column.ColumnName,
                from row in table.AsEnumerable()
                select new XElement(row.Field<string>(metaIndex), row[column])
                )
            )
        );

    return xdoc.ToString();
}

The result was another format which is not nested XML as I explained. see image

How can I convert my table into the XML format I need?

2
  • datatable,writeXML will write it out in a format it needs for reading it back Commented Oct 5, 2016 at 20:54
  • no I also tried that, it returns just one node, you can try it, but it is wrong Commented Oct 5, 2016 at 21:02

2 Answers 2

1

You need to use GroupBy to group the rows, then select the parts you want into XElements.
The code below should do what you want:

    var xml = new XElement(table.TableName, table.Rows.Cast<DataRow>()
        .GroupBy(row => (string)row[0])
        .Select(g =>
            new XElement(table.Columns[0].ColumnName,
                new XElement("label", g.Key),
                g.GroupBy(row => (string)row[1])
                 .Select(g1 =>
                    new XElement(table.Columns[1].ColumnName,
                        new XElement("label", g1.Key),
                        new XElement(table.Columns[2].ColumnName,
                            g1.Select(row =>
                                new XElement("label", (string)row[2])
                            )
                        )
                    )
                )
            )
        )
    ).ToString();

Fiddle: https://dotnetfiddle.net/qEWNvj

Sign up to request clarification or add additional context in comments.

1 Comment

No problem; glad I could help.
0

My style is a little different from other answers. The code is tested and matches your expected results.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("A", typeof(string));
            dt.Columns.Add("B", typeof(string));
            dt.Columns.Add("C", typeof(string));

            dt.Rows.Add(new object[] {"A1", "B1","C1"});
            dt.Rows.Add(new object[] {"A1", "B1","C2"});
            dt.Rows.Add(new object[] {"A1", "B1","C3"});
            dt.Rows.Add(new object[] {"A1", "B2","C1"});
            dt.Rows.Add(new object[] {"A1", "B2","C2"});

            dt = dt.AsEnumerable()
                .OrderBy(x => x.Field<string>("A"))
                .ThenBy(x => x.Field<string>("B"))
                .ThenBy(x => x.Field<string>("C"))
                .CopyToDataTable();

            XElement data = new XElement("Data", new XElement("A", dt.AsEnumerable()
                .GroupBy(g1 => g1.Field<string>("A")).Select(g1a =>  new object[] { 
                    new XElement("lable",(string)g1a.Key),
                    new XElement("B",
                        g1a.GroupBy(g2 => g2.Field<string>("B")).Select(g2b => new object[] {
                            new XElement("lable", (string)g2b.Key),
                            new XElement("C",
                                g2b.Select(g3c => new XElement("lable", g3c.Field<string>("C"))
                            ))}
                    ))}
            )));

        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.