我有一个重度嵌套的XML文档,我需要将其加载到我的数据库中以进行其他处理。由于超出本讨论范围的各种原因,我需要“扁平化”。该结构向下,然后将其加载到DataTables然后我可以SQLBulkCopy它进入数据库,它将被处理。所以假设我的原始XML看起来像这样(我的嵌套更加严重,但这是基本的想法):
<data>
<report id="1234" name="XYZ">
<department id="234" name="Accounting">
<item id="ABCD" name="some item">
<detail id="detail1" value="1"/>
<detail id="detail2" value="2"/>
<detail id="detail3" value="3"/>
</item>
</department>
</report>
</data>
我希望将其压缩成单个(尽管是多余的)表结构,其中每个属性都成为一列(即ReportId,ReportName,DepartmentId,DepartmentName,ItemId,ItemName,Detail1,Detail2,Detail3)。
所以我的问题很简单,是否可以通过简单的Linq查询来实现这一目标&#39;?在过去,我会写一些XSLT并完成它,但我很好奇Linq库是否可以完成同样的事情?
谢谢!
答案 0 :(得分:3)
这是你要找的吗?
var doc = XDocument.Load(fileName);
var details =
from report in doc.Root.Elements("report")
from department in report.Elements("department")
from item in department.Elements("item")
from detail in item.Elements("detail")
select new
{
ReportId = (int)report.Attribute("id"),
ReportName = (string)report.Attribute("name"),
DepartmentId = (int)department.Attribute("id"),
DepartmentName = (string)department.Attribute("name"),
ItemId = (string)item.Attribute("id"),
ItemName = (string)item.Attribute("name"),
DetailId = (string)detail.Attribute("id"),
DetailValue = (int)detail.Attribute("value"),
};
如果您想将其作为DataTable
,则可以使用以下扩展方法:
public static DataTable ToDataTable<T>(this IEnumerable<T> source)
{
PropertyInfo[] properties = typeof(T).GetProperties()
.Where(p => p.CanRead && !p.GetIndexParameters().Any())
.ToArray();
DataTable table = new DataTable();
foreach (var p in properties)
{
Type type = p.PropertyType;
bool allowNull = !type.IsValueType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
allowNull = true;
type = Nullable.GetUnderlyingType(type);
}
DataColumn column = table.Columns.Add(p.Name, type);
column.AllowDBNull = allowNull;
column.ReadOnly = !p.CanWrite;
}
foreach (var item in source)
{
DataRow row = table.NewRow();
foreach (var p in properties)
{
object value = p.GetValue(item, null) ?? DBNull.Value;
row[p.Name] = value;
}
table.Rows.Add(row);
}
return table;
}
像这样使用:
var table = details.CopyToDataTable();