如何读取XML全部值?DataSet.ReadXml仅获前四项的问题解决
问题分析与解决方案
你遇到的问题根源在于DataSet.ReadXml()处理嵌套XML结构的方式——它会根据XML的层级自动生成多个关联的DataTable,而你的代码只读取了第一个DataTable(对应<session>节点),所以只能拿到session的四个属性值。
为什么会这样?
你的XML是多层嵌套结构:
<session>→<appliance>→<test_set>→<test>/<test_result>
每个节点都有自己的属性,DataSet.ReadXml()会为每个节点创建一个独立的DataTable,同时自动生成DataRelation来维护它们的父子关系。你当前的Dt.Load(ds.CreateDataReader())只会读取DataSet中的第一个表(也就是session表),自然看不到后面层级的数据。
解决方案:手动整合所有层级的数据到一个DataTable
我们可以利用DataSet自动生成的关系,遍历所有层级的记录,把所有属性合并到一个统一的DataTable中。以下是具体实现代码:
public System.Data.DataTable CreateDataTableFromXml(string XmlFile) { System.Data.DataTable mergedTable = new System.Data.DataTable(); try { DataSet ds = new DataSet(); ds.ReadXml(XmlFile); // 1. 添加所有需要的列(从各个层级的表中收集) foreach (DataTable table in ds.Tables) { foreach (DataColumn col in table.Columns) { if (!mergedTable.Columns.Contains(col.ColumnName)) { mergedTable.Columns.Add(col.ColumnName, col.DataType); } } } // 2. 遍历session表,关联后续层级的数据 foreach (DataRow sessionRow in ds.Tables["session"].Rows) { // 获取关联的appliance行 DataRow[] applianceRows = sessionRow.GetChildRows(ds.Relations["session_appliance"]); foreach (DataRow applianceRow in applianceRows) { // 获取关联的test_set行 DataRow[] testSetRows = applianceRow.GetChildRows(ds.Relations["appliance_test_set"]); foreach (DataRow testSetRow in testSetRows) { // 获取关联的test和test_result行 DataRow[] testRows = testSetRow.GetChildRows(ds.Relations["test_set_test"]); DataRow[] testResultRows = testSetRow.GetChildRows(ds.Relations["test_set_test_result"]); // 创建新行,填充所有层级的数据 DataRow newRow = mergedTable.NewRow(); // 填充session数据 foreach (DataColumn col in ds.Tables["session"].Columns) { newRow[col.ColumnName] = sessionRow[col]; } // 填充appliance数据 foreach (DataColumn col in ds.Tables["appliance"].Columns) { newRow[col.ColumnName] = applianceRow[col]; } // 填充test_set数据 foreach (DataColumn col in ds.Tables["test_set"].Columns) { newRow[col.ColumnName] = testSetRow[col]; } // 填充test数据(如果有) if (testRows.Length > 0) { foreach (DataColumn col in ds.Tables["test"].Columns) { newRow[col.ColumnName] = testRows[0][col]; } } // 填充test_result数据(如果有) if (testResultRows.Length > 0) { foreach (DataColumn col in ds.Tables["test_result"].Columns) { newRow[col.ColumnName] = testResultRows[0][col]; } } mergedTable.Rows.Add(newRow); } } } } catch (Exception ex) { // 不要空捕获,至少记录异常信息 Console.WriteLine($"读取XML时出错:{ex.Message}"); throw; // 或者根据需求处理异常 } return mergedTable; }
额外提示
- 不要忽略异常:你原来的代码中
catch块是空的,这会导致出错时无法排查问题,建议添加日志或重新抛出异常。 - 关系名称的确认:DataSet自动生成的关系名称通常是
父表名_子表名,如果不确定,可以通过ds.Relations查看具体名称。 - XML结构的兼容性:如果你的XML有多个
<appliance>或多个<test>在一个<test_set>下,代码需要做相应调整(比如处理多行的情况),当前代码假设每个层级是一对一或一对多但只取第一条,你可以根据实际需求修改。
内容的提问来源于stack exchange,提问作者Dimitris
相关产品推荐
相关产品推荐

