将具有多个嵌套级别的任何 XML 读取到结构化表中以写入 Excel 的通用方法
Posted
技术标签:
【中文标题】将具有多个嵌套级别的任何 XML 读取到结构化表中以写入 Excel 的通用方法【英文标题】:Generic way to read any XML with multiple nested levels into structured tables, to be written to Excel 【发布时间】:2021-01-12 02:57:51 【问题描述】:我正在尝试读取由第三方应用程序(没有 XSD 文档)生成的 XML 文件,其中包含多个嵌套级别。
我的目标是以结构化方式遍历 XML 数据,并写入 Excel 文件中的多个工作表,以便进一步分析数据。
XML 文件可以有任意数量的嵌套级别,并且每个级别中有任意数量的字段。 XML中没有提到字段的数据类型,也没有schema(schema必须推断出来),但是每个字段的数据类型都可以被认为是string。如果一个字段的数据类型也可以推断出来,那就更好了,但我可以不用这个。
在同一级别内,某些字段可能出现在某些记录中,而可能不会出现在其他记录中。 唯一要处理的节点是元素和属性。不会有任何 cmets 或 CDATA 部分。
以下 XML 仅作为示例给出。实际的 XML 可能会有所不同。
请注意DocRemarks
存在于第二个文档中,但不存在于第一个文档中,而DocStatus
仅存在于第一个文档中。第二个文档标签具有IsDraft
属性。 2nd Document 在ItemLine
下有ItemBatch
记录,用于第二个项目,但其他项目都没有这些记录。
<Main>
<Document>
<CustomerName>ABC</CustomerName>
<DocDate>01-Jan-2020</DocDate>
<DocNum>1</DocNum>
<ItemLine>
<ItemName>Item1</ItemName>
<ItemQty>100</ItemQty>
</ItemLine>
<ItemLine>
<ItemName>Item2</ItemName>
<ItemQty>90</ItemQty>
</ItemLine>
<DocStatus>Approved</DocStatus>
</Document>
<Document IsDraft="Yes">
<CustomerName>ABC</CustomerName>
<DocDate>02-Jan-2020</DocDate>
<DocNum>2</DocNum>
<ItemLine>
<ItemName>Item1</ItemName>
<ItemQty>100</ItemQty>
</ItemLine>
<ItemLine>
<ItemName>Item2</ItemName>
<ItemQty>90</ItemQty>
<ItemBatch>
<BatchName>B1</BatchName>
<BatchQty>30</BatchQty>
</ItemBatch>
<ItemBatch>
<BatchName>B2</BatchName>
<BatchQty>60</BatchQty>
</ItemBatch>
</ItemLine>
<DocRemarks>My Remarks</DocRemarks>
</Document>
</Main>
最终目标是将Document
的所有直接子字段放在一个 Excel 表中,ItemLine
的所有子字段在第二张表中,ItemBatch
的所有子字段在下一张表中,依此类推关联哪些子记录属于哪个父级别,反之亦然。
我尝试过的:
我用过DataSet.ReadXml
方法,使用InferSchema
参数。
DataTable dt = new DataTable();
DataSet ds = new DataSet();
try
ds = new DataSet();
ds.ReadXml(xmlFileName, XmlReadMode.InferSchema);
catch (Exception ex)
这会生成一个包含 3 个 DataTables 的 DataSet:Document、ItemLine 和 ItemBatch。
问题:
加载数据集后,我需要按照数据表的逻辑顺序写入 Excel。
在这种情况下,第一张应该是Document
,第二张应该是ItemLine
,第三张应该是ItemBatch
。一个父表可以有多个子表,例如Document
可以有ItemLine
和GLLine
表(示例XML 中未显示)
我如何确定名为 Document
的表转到表 1,ItemLine
转到表 2,等等?我无法对表名进行硬编码。
在每张表中,即对于每个数据表,我需要在写出其他列之前在每个开头写下主键、外键的列。例如,对于Document
表,DataTable 有一个自动生成的列Document_Id
。这应该是 Excel 工作表中的第一列。
对于ItemLine
表,DataTable 具有ItemLine_Id
和Document_Id
自动生成的列。在这种情况下,我希望这 2 个作为 Excel 工作表中的第 2 列。
【问题讨论】:
DataSet 方法 ReadXml 创建无法重新组合的碎片 DataTable。 ReadXml 使第一个 xml 标记为表名,第二个 xml 标记列名,第三个 xml 标记行数据。一旦获得超过三个或具有 xml 属性,结果就是一大堆零散的表。 我只需要知道每个级别的 XML 中的 DataTables,以便我可以以相同的顺序写入 Excel。对于每个 DataTable,我需要知道主键和外键的自动生成的列名是什么。 正如我所说,它是支离破碎的,你无法理解这些碎片。 【参考方案1】:试试这个,你应该可以将嵌套标签加载到单独的表格中:
public string ReadXMLFile(HttpRequestMessage request)
var response = "";
DataSet ds = new DataSet();
ds.ReadXml((request.Content.ReadAsStreamAsync().Result));
if (ds.Tables.Count > 0)
//Code Here for Insert or Any Other
return response;
【讨论】:
以上是关于将具有多个嵌套级别的任何 XML 读取到结构化表中以写入 Excel 的通用方法的主要内容,如果未能解决你的问题,请参考以下文章