将具有多个嵌套级别的任何 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 可以有ItemLineGLLine 表(示例XML 中未显示)

    我如何确定名为 Document 的表转到表 1,ItemLine 转到表 2,等等?我无法对表名进行硬编码。

    在每张表中,即对于每个数据表,我需要在写出其他列之前在每个开头写下主键、外键的列。例如,对于Document 表,DataTable 有一个自动生成的列Document_Id。这应该是 Excel 工作表中的第一列。

对于ItemLine 表,DataTable 具有ItemLine_IdDocument_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 的通用方法的主要内容,如果未能解决你的问题,请参考以下文章

具有 3 个级别的 MongoDB 嵌套查找并将新值附加到结果文档

用于编辑具有多级节点和多个用户的层次结构的架构

将 XML 数据插入到具有多个节点的 SQL 表中

具有 3 个级别的 MongoDB 嵌套查找

尝试读取 BigQuery 表中的 JSON 结构时出错

读取具有多个名称空间的子节点