André Luis
André Luis

Reputation: 23

Fill a datagridview with specific XML node from several XML files

I have to fill a datagridview with 3 specifics XML nodes data from several XML files.

Here it´s an example:

<?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>

I need these get 3 tags - <numero_nfse>, <data_nfse>, <cod_verificador_autenticidade> - and load them into a datagridview.

However, there are more XML files, with the same tags and I would to load all of them at the same time into a datagridview.

I wrote the code bellow and as you can see, it´s not working.

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];
}

To clarify: I want one column for each tag. So my datagridview would be with 3 columns and as many rows as there are files in the directory. There´s only one <retorno> in each XML file.

Can anyone help me?

Upvotes: 1

Views: 182

Answers (1)

dbc
dbc

Reputation: 117190

You are loading your multiple XML files into a DataSet with one DataTable for each file, but as explained in How to bind Dataset to DataGridView in windows application you can only bind a single DataTable to a DataGridView.

Since you have only one <retorno> node in each file, it would make sense to load the files into a DataTable with 3 columns - one each for <numero_nfse>, <data_nfse>, and <cod_verificador_autenticidade> - and one row for each file.

The following code does this:

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;
}

Note I have switch to the LINQ to XML API which is generally easier to work with than the old XmlDocument API.

Demo fiddle here.

Upvotes: 1

Related Questions