使用多个 XML 文件中的特定 XML 节点填充 datagridview

Posted

技术标签:

【中文标题】使用多个 XML 文件中的特定 XML 节点填充 datagridview【英文标题】:Fill a datagridview with specific XML node from several XML files 【发布时间】:2020-09-08 18:14:33 【问题描述】:

我必须用来自多个 XML 文件的 3 个特定 XML 节点数据填充 datagridview。

这是一个例子:

<?xml version='1.0' encoding='iso-8859-1'?>
<retorno>
    <mensagem>
        <codigo>00001 - Sucesso</codigo>
    </mensagem>
    <alerta>
    </alerta>
    <numero_nfse>641</numero_nfse>
    <serie_nfse>1</serie_nfse>
    <data_nfse>08/09/2020</data_nfse>
    <hora_nfse>12:16:10</hora_nfse>
    <arquivo_gerador_nfse>688569.xml</arquivo_gerador_nfse>
    <cod_verificador_autenticidade>03379569</cod_verificador_autenticidade>
</retorno>

我需要这些获得 3 个标签 - &lt;numero_nfse&gt;&lt;data_nfse&gt;&lt;cod_verificador_autenticidade&gt; - 并将它们加载到数据网格视图中。

但是,有更多的 XML 文件,具有相同的标签,我会同时将所有这些文件加载​​到 datagridview 中。

我编写了下面的代码,如您所见,它不起作用。

string[] arquivos = Directory.GetFiles(@"D:\Documentos\retorno");
DataSet retorno = new DataSet();

for (int j = 0; j < arquivos.Length; j++)

    FileInfo Xmls = new FileInfo(arquivos[j]);

    string caminhoXmls = Convert.ToString(Xmls);

    XmlDocument retornoXml = new XmlDocument();
    retornoXml.Load(caminhoXmls);

    XmlNodeList retornoTags = retornoXml.GetElementsByTagName("retorno");
    foreach (XmlNode xn in retornoTags)
    
        string XmlNumeroNfse = xn["numero_nfse"].InnerText;
        string XmlDataNfse = xn["data_nfse"].InnerText;
        string XmlHoraNfse = xn["hora_nfse"].InnerText;
        string XmlCodigo = xn["cod_verificador_autenticidade"].InnerText;
    

    retorno.ReadXml(caminhoXmls);

    dgvDadosNota.DataSource = retorno.Tables[j];

澄清一下:我希望每个标签有一列。因此,我的 datagridview 将包含 3 列和与目录中的文件一样多的行。每个 XML 文件中只有一个 &lt;retorno&gt;

谁能帮帮我?

【问题讨论】:

请edit 分享您尝试加载的XML 的(简化)示例——即minimal reproducible example。 GetElementsByTagName() 已弃用 BTW:建议您使用 XmlNode.SelectNodesXmlNode.SelectSingleNode 方法而不是 GetElementsByTagName 方法。 最好使用 LINQ to XML。 您正在为每个文件使用DataSet 和一个DataTable。那是你真正想做的吗?为每个 XML 文件使用具有 3 列和 1 行的单个 DataTable 不是更有意义吗?当您执行dgvDadosNota.DataSource = retorno.Tables[j]; 时,您将覆盖以前的绑定,因此您当然只会看到一个结果。 我的目标是读取该目录中的每个 XML 文件,获取每个文件中的具体标签并将它们加载到 datagridview 中。 @AndréLuis - 每个文件一行,&lt;numero_nfse&gt;&lt;data_nfse&gt;&lt;cod_verificador_autenticidade&gt; 各一列?或者每个文件中是否可以有多个&lt;retorno&gt; 标签?因为不能将整个DataSet 绑定到DataGridView,所以只能绑定特定的DataTable。见How to bind Dataset to DataGridView in windows application。 【参考方案1】:

您正在将多个 XML 文件加载到 DataSet 中,每个文件都有一个 DataTable,但如 How to bind Dataset to DataGridView in windows application 中所述,您只能绑定一个 单个 DataTable DataGridView

由于每个文件中只有一个 &lt;retorno&gt; 节点,因此将文件加载到具有 3 列的 DataTable 是有意义的 - &lt;numero_nfse&gt;&lt;data_nfse&gt;&lt;cod_verificador_autenticidade&gt; 各一列 - 和每个文件一行。

下面的代码就是这样做的:

static DataTable CreateDataTableFromRetornoXML(IEnumerable<string> fileNames)

    var columnNames = new []
    
        "numero_nfse",
        "data_nfse",
        "cod_verificador_autenticidade",
    ;
    var rootName = "retorno";
    
    var table = new DataTable();
    foreach (var name in columnNames)
        table.Columns.Add(name, typeof(string));
    
    foreach (var fileName in fileNames)
    
        var row = table.NewRow();
        var root = XElement.Load(fileName);
        var retorno = root.DescendantsAndSelf(rootName).Single(); // There should be only one.
        foreach (DataColumn column in table.Columns)
        
            row[column] = retorno.Element(column.ColumnName)?.Value;
        
        table.Rows.Add(row);
    
    
    return table;

请注意,我已切换到 LINQ to XML API,它通常比旧的 XmlDocument API 更易于使用。

演示小提琴here.

【讨论】:

以上是关于使用多个 XML 文件中的特定 XML 节点填充 datagridview的主要内容,如果未能解决你的问题,请参考以下文章

在 XML 文件中保存特定节点

如何使用 vbscript 删除 XML 文件中的特定节点

有没有办法使用 XSLT 基于 XML 中的元素复制 XML 节点 n 次?

有没有办法使用 XSLT 基于 XML 中的元素复制 XML 节点 n 次?

使用php替换xml中的特定节点值

动态地向Recycler视图添加多个视图