使用 C#/Linq 将 XML 平展到 DataGridView

本文关键字:DataGridView XML Linq 使用 | 更新日期: 2023-09-27 17:57:18

有很多

这样的问题,但我可以向你保证,这个问题非常独特!我需要一个通用解决方案将 XML 数据平展为两列网格(字段、值),但真正的挑战是每个响应的 XML 数据的层次结构都不同!

这是以XML格式存储在数据库中的审计数据,我无法更改这些响应的结构,但需要处理任何可能的层次结构,并在简单的网格中向用户显示结果。

下面是 XML 结构的示例:

<xml>
  <results>
    <resultsDTO>
      <reportid>173601</reportid>
      <results>
        <displayName>Item 1</displayName>
        <someParameter>blahblah</someParameter>
        <hidden>false</hidden>
        <values>
          <value>10</value>
          <resultType>PERCENTAGE</resultType>
        </values>
        <values>
          <value>some.pdf</value>
          <resultType>PDF</resultType>
        </values>
        <values>
          <value>Findings of Item 1</value>
          <resultType>FINDINGS</resultType>
        </values>
      </results>
      <results>
        <displayName>Item 2</displayName>
        <someParameter>blahblah</someParameter>
        <hidden>false</hidden>
        <values>
          <value>20</value>
          <resultType>PERCENTAGE</resultType>
        </values>
        <values>
          <value/>
          <resultType>PDF</resultType>
        </values>
        <values>
          <value>Findings of Item 2</value>
          <resultType>FINDINGS</resultType>
        </values>
      </results>
      <reportTexts>
        <value/>
        <resultType>HISTORY</resultType>
      </reportTexts>
      <reportTexts>
        <value>Some info here.</value>
        <resultType>INFORMATION</resultType>
      </reportTexts>
    </resultsDTO>
  </results>
</xml>
正如您从 XML 中看到的那样,在同一级别上总是有一个"resultType"和

"value",但是我需要一种方法来遍历此 XML,而无需定义任何硬编码路径(XML/Results/ResultsDTO/Results/Values/),这些路径将在任何级别找到这些 resultType 和值,并且还处理一些特殊的数据规则。

我正在尝试将这些值放入 GridView 输出中,如下所示:

[Field], [Value]
Item 1 - Percentage, 10
Item 1 - Findings, Findings of Item 1
Item 2 - Percentage, 20
Item 2 - Findings, Findings of Item 2
History, NULL
Information, Some info here.

这是我当前的代码,它显示了我想要实现的目标的一半:

XDocument doc = XDocument.Load(@"XMLFile1.xml");
var query = from c in doc.Descendants("xml").Elements("results").Elements("resultsDTO").Elements("results").Elements("values").Where(n => n.Element("resultType").Value != "PDF")
            select new
            {
                Field = c.Parent.Element("displayName") == null ? c.Element("resultType").Value : c.Parent.Element("displayName").Value + " - " + c.Element("resultType").Value,
                Value = c.Element("value").Value        
            };
dataGridView1.DataSource = query.ToList();

我正在禁止显示"PDF"结果类型,并将显示名称附加到结果类型(如果它存在于父节点中!),因为它不适用于其他节点。

这目前只获取XML/Results/ResultsDTO/Results/

Values/下的值,而不是XML/Results/ResultsDTO/ReportTexts中的值。

任何帮助将不胜感激!谢谢。

使用 C#/Linq 将 XML 平展到 DataGridView

你在大多数情况下是对的。您需要做的就是:

  1. 也联合了报告文本元素的后代。
  2. 后代不需要你遍历路径。 您可以提供任何起始路径。

使用以下查询:

 var query = from c in doc.Descendants("values").Union(doc.Descendants("reportTexts")).Where(n => n.Element("resultType").Value != "PDF")
             select new
             {
              Field = c.Parent.Element("displayName") == null ? c.Element("resultType").Value : c.Parent.Element("displayName").Value + " - " + c.Element("resultType").Value,
              Value = c.Element("value").Value // you can replace "" by null here
             };

输出如下:

[Field], [Value]
Item 1 - Percentage, 10
Item 1 - Findings, Findings of Item 1
Item 2 - Percentage, 20
Item 2 - Findings, Findings of Item 2
History, ""
Information, Some info here.