The problem:
You state in your comments that you are unsure how to add the inner elements which will create the attributes in your resulting XML. The rest of your code works perfectly, except this bit:
//I am unable to write the next line
xInnerElt[j] = new XElement(InnerTagName,new XAttribute((XName)ColumnName,rows Item arry)),
The Solution
The missing part you want is to loop through the columns which are on the DataTable, and then access the values of the columns per row. This is because the DataRow object doesn't have information about the column names.
Therefore you need another inner loop through the DataTable.Columns collection, and then use the DataRow column accessor dt.Rows[j][column] to get the value from the current column.
It looks like this:
foreach (var column in dt[i].Columns)
{
xInnerElt[j].Add(
new XAttribute(
(column as DataColumn).ColumnName,
dt[i].Rows[j][(column as DataColumn)].ToString()
)
);
}
My test with your code:
using System;
using System.Collections.Generic;
using System.Data;
using System.Xml.Linq;
namespace XElemFromDT
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> htAtributNameForTable = new Dictionary<string, string>()
{
{ "Software", "software_entry" },
{ "ApplicationConfigurations", "config" }
};
DataTable dt1 = new DataTable();
dt1.TableName = "Software";
dt1.Columns.Add("name", typeof(string));
dt1.Columns.Add("path", typeof(string));
dt1.Rows.Add("Adobe Acrobat X Standard", @"Applications\Acrobat\Acrobat XStandard\AcroStan.msi");
dt1.Rows.Add("Adobe Photoshop", @"Applications\Photoshop\Photoshop.msi");
DataTable dt2 = new DataTable();
dt2.TableName = "ApplicationConfigurations";
dt2.Columns.Add("name", typeof(string));
dt2.Columns.Add("value", typeof(string));
dt2.Rows.Add("someName", "someValue");
dt2.Rows.Add("someOtherName", "someOtherValue");
DataTable[] dt = new DataTable[] { dt1, dt2 };
XDocument xDoc = new XDocument(new XElement("Root"));
for (int i = 0; i < dt.Length; i++) //for every table
{
XName TableName = dt[i].TableName; //table name.
XElement[] xInnerElt = new XElement[dt[i].Rows.Count]; //for n rows inside one table
for (int j = 0; j < dt[i].Rows.Count; j++) //loop each tag inside the table
{
XName InnerTagName = htAtributNameForTable[dt[i].TableName].ToString(); //tag name form hash table. i.e, software_entry
//I am unable to write the next line
xInnerElt[j] = new XElement(InnerTagName);
foreach (var column in dt[i].Columns)
{
xInnerElt[j].Add(
new XAttribute(
(column as DataColumn).ColumnName,
dt[i].Rows[j][(column as DataColumn)].ToString()
)
);
}
}
XElement xElt = new XElement(TableName, xInnerElt); //one table aded to tag.
xDoc.Root.Add(xElt);
}
Console.WriteLine(xDoc.ToString());
Console.ReadKey();
}
}
}
Bonus -- because I had to try this
Here's a way to do it using LINQ completely: (using same test data as my previous example)
DataTable[] dt = new DataTable[] { dt1, dt2 };
XDocument xDoc = new XDocument(new XElement("Root"));
Func<DataTable, DataRow, IEnumerable<XAttribute>> getAttributes = (t, r) =>
t.Columns.OfType<DataColumn>().Select(c => new XAttribute(c.ColumnName, r[c].ToString()));
Func<DataTable, IEnumerable<XElement>> getElements = t =>
t.Rows.OfType<DataRow>().Select(r => new XElement(htAtributNameForTable[t.TableName], getAttributes(t, r)));
Func<DataTable[], IEnumerable<XElement>> getTables = dtc =>
dtc.AsEnumerable().Select(t => new XElement(t.TableName, getElements(t)));
xDoc.Root.Add(getTables(dt));
DataTableto xml file?