问题:
您在评论中声明您不确定如何添加将在生成的 XML 中创建属性的内部元素。您的代码的其余部分工作完美,除了这一点:
//I am unable to write the next line
xInnerElt[j] = new XElement(InnerTagName,new XAttribute((XName)ColumnName,rows Item arry)),
解决方案
您想要的缺失部分是遍历 上的列DataTable
,然后访问每行列的值。这是因为该DataRow
对象没有关于列名的信息。
因此,您需要通过集合进行另一个内部循环DataTable.Columns
,然后使用DataRow
列访问器dt.Rows[j][column]
从当前列中获取值。
它看起来像这样:
foreach (var column in dt[i].Columns)
{
xInnerElt[j].Add(
new XAttribute(
(column as DataColumn).ColumnName,
dt[i].Rows[j][(column as DataColumn)].ToString()
)
);
}
我对您的代码的测试:
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();
}
}
}
奖金——因为我必须试试这个
这是一种完全使用 LINQ 的方法:(使用与我之前的示例相同的测试数据)
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));