如何读取嵌套XML并转换为单表结构存入数据库?
如何将嵌套XML读取为单表结构并存入数据库?
这个问题我之前碰到好多次了——用DataSet.ReadXml()读嵌套XML的时候,它总会老老实实按照XML的层级拆成好几张关联表,但咱们要的是扁平化的单表数据对吧?别担心,有两个靠谱的方案可以解决:
你的示例XML(已修正语法错误)
<bookinfo> <author> <name>test</name> <contact>155335852</contact> </author> <books> <book> <title>abc</title> <price>152</price> </book> <book> <title>xyz</title> <price>1523</price> </book> </books> </bookinfo>
注:原XML里的<title>abc</book>标签闭合错误,已修正为</title>,否则解析会失败。
期望的单表结果
| author | contact | book | Price |
|---|---|---|---|
| test | 155335852 | abc | 152 |
| test | 155335852 | xyz | 1523 |
方案一:用LINQ to XML直接扁平化解析(推荐,灵活可控)
这种方法跳过DataSet的自动拆分,手动提取需要的字段并组合,完全按照你的需求生成单表,代码直观且容易维护:
using System.Xml.Linq; using System.Data; // 加载XML文档(也可以用字符串直接解析:XDocument.Parse(xmlString)) XDocument doc = XDocument.Load("你的XML文件路径"); // 提取作者的基础信息 var authorNode = doc.Descendants("author").FirstOrDefault(); string authorName = authorNode?.Element("name")?.Value; string authorContact = authorNode?.Element("contact")?.Value; // 遍历所有书籍,和作者信息组合成扁平化数据 var flatData = from bookNode in doc.Descendants("book") select new { Author = authorName, Contact = authorContact, BookTitle = bookNode.Element("title")?.Value, Price = bookNode.Element("price")?.Value }; // 转换为DataTable(方便后续存入数据库) DataTable resultTable = new DataTable(); resultTable.Columns.Add("author"); resultTable.Columns.Add("contact"); resultTable.Columns.Add("book"); resultTable.Columns.Add("Price"); foreach (var item in flatData) { resultTable.Rows.Add(item.Author, item.Contact, item.BookTitle, item.Price); } // 之后就可以用resultTable直接执行数据库插入操作了
方案二:利用DataSet的表关联合并数据
如果你的项目已经依赖DataSet,也可以通过自动生成的关联ID把多表数据合并:
using System.Data; DataSet ds = new DataSet(); ds.ReadXml("你的XML文件路径"); // DataSet会自动生成多张表(比如bookinfo、author、books、book),并添加关联ID字段 var mergedData = from bookinfo in ds.Tables["bookinfo"].AsEnumerable() join author in ds.Tables["author"].AsEnumerable() on bookinfo.Field<int>("bookinfo_Id") equals author.Field<int>("bookinfo_Id") join books in ds.Tables["books"].AsEnumerable() on bookinfo.Field<int>("bookinfo_Id") equals books.Field<int>("bookinfo_Id") join book in ds.Tables["book"].AsEnumerable() on books.Field<int>("books_Id") equals book.Field<int>("books_Id") select new { Author = author.Field<string>("name"), Contact = author.Field<string>("contact"), BookTitle = book.Field<string>("title"), Price = book.Field<string>("price") }; // 转换为DataTable DataTable resultTable = new DataTable(); resultTable.Columns.Add("author"); resultTable.Columns.Add("contact"); resultTable.Columns.Add("book"); resultTable.Columns.Add("Price"); foreach (var item in mergedData) { resultTable.Rows.Add(item.Author, item.Contact, item.BookTitle, item.Price); }
两种方案对比
- 方案一:代码更简洁,不需要关心DataSet的自动表结构,适合大多数场景;
- 方案二:适合已经在使用DataSet的项目,但需要熟悉自动生成的关联字段名称。
不管选哪种,最终都能得到你需要的单表结构,直接存入数据库即可。
内容的提问来源于stack exchange,提问作者Abid Zahid
相关产品推荐
相关产品推荐

