C# - Acessando e Lendo arquivos XML recursivamente


 Hoje eu vou mostrar como podemos acessar e ler arquivos XML usando a técnica da recursão na linguagem C#.

 

Um algoritmo é recursivo quando ele usa a si mesmo, mas com parâmetros diferentes, para resolver um problema.

A Recursão é uma técnica de programação importante que faz com que uma função invoque a si mesmo. Um exemplo é o cálculo de fatoriais.

Abaixo vemos um código em VB .NET e C# que mostra como calcular o Fatorial de um número usando recursão:

  Function factorial(ByVal n As Integer) As Integer
        If n <= 1 Then
            Return 1
        Else
            Return factorial(n - 1) * n
        End If
    End Function

 

public int factorial(int n)
{
	if (n <= 1) {
		return 1;
	} else {
		return factorial(n - 1) * n;
	}
}

 

VB .NET C#

Observe que a função factorial() chama a si mesma repetidas vezes para calcular o resultado.

Para possibilitar a recursão, o sistema operacional fornece a cada programa uma pequena quantidade de espaço na memória, a pilha de chamadas.

Dessa forma um problema que pode ocorrer com a recursão é que uma função recursiva pode usar todos os recursos disponíveis (como o espaço de memória e a pilha do sistema).

Cada vez que uma função recursiva chama a si mesma ela usa recursos do sistema e esses recursos são liberados quando a função recursiva encerra, assim, uma função recursiva com muitos níveis de recursão pode usar todos os recursos disponíveis do sistema.

Se você suspeitar de qualquer chance de uma recursão excessiva (ou infinita), crie a função para contar o número de vezes que ela chama a si mesma e defina um número limite de chamadas. Se a função chama a si mesmo mais vezes que o limite, a função deve ser encerrada automaticamente. O número ideal de máximo de iterações depende da função recursiva.

Nestes artigos : .NET - O Algoritmo de Euclides, VB .NET - Números e seqüência de Fibonacci eu mostro como usar a recursão tanto na linguagem VB .NET como na linguagem C#.

No artigo de hoje eu vou mostrar como acessar e obter informações específicas de um arquivo XML usando a recursão.

 

Recursos usados :

Criando o projeto no VS 2013

Abra o VS 2013 Express for Windows desktop e clique em New Project;

A seguir selecione Visual C# -> Windows Forms Application;

Informe o nome Lendo_XML_Recursivamente e clique no botão OK;

Agora vamos criar um arquivo XML no projeto clicando no menu PROJECT -> Add New Item;

Selecione a opção XML File, informe o nome Projetos.xml e a seguir inclua o código abaixo neste arquivo:

<?xml version="1.0" encoding="utf-8" ?> 
<funcionarios>
    <funcionario Id="1001" Nome="Macoratti" Cargo="Desenvolvedor">    
        <projetos>
            <projeto Codigo="Mondial">                
                <orcamento>7000</orcamento>
            </projeto>
        </projetos>
    </funcionario>
    <funcionario Id="1002" Nome="Janice" Cargo="Helpdesk">    
        <projetos>
            <projeto Codigo="Orlando">                
                <orcamento>1000</orcamento>
            </projeto>
            <projeto Codigo="Azure">                
                <orcamento>900</orcamento>
            </projeto>
        </projetos>
    </funcionario>
    
    <funcionario Id="1003" Nome="Jefferson" Cargo="Arquiteto">        
        <projetos>            
            <projeto Codigo="Azure">                
                <orcamento>900</orcamento>
            </projeto>
            <projeto Codigo="Mondial">                
                <orcamento>7000</orcamento>
            </projeto>
            <projeto Codigo="Orlando">                
                <orcamento>1000</orcamento>
            </projeto>
        </projetos>
  </funcionario>  
 
   <funcionario Id="1004" Nome="Jessica" Cargo="Design">        
        <projetos>            
            <projeto Codigo="Mondial">                
                <orcamento>7000</orcamento>
            </projeto>
            <projeto Codigo="Orlando">                
                <orcamento>1000</orcamento>
            </projeto>
        </projetos>
    </funcionario>  
</funcionarios>

Nosso objetivo será acessar os nomes dos funcionários alocados por projetos neste arquivo XML usando recursão.

Criando a interface com o usuário

Vamos agora definir a interface com o usuário incluindo no formulário form1.cs do projeto os seguintes controles a partir da ToolBox:

Disponha os controles no formulário conforme o leiaute da figura abaixo:

Vamos definir no início do formulários os seguintes namespaces usados no projeto:

using System;

using System.Windows.Forms;

using System.Xml;

Acessando e lendo o arquivo XML

Na plataforma .NET você tem disponível diversas formas de acessar e ler arquivos XML as mais usadas usam os seguintes recursos:

Eu já abordei praticamente todos os recursos acima para ler arquivos XML e neste artigo eu vou acessar o arquivo XML usando a classe XMLTextReader.

Eu vou apenas exibir o conteúdo do arquivo XML sem formatação pois o objetivo do artigo é ler o arquivo XML usando recursão.

No controle ListBox - lbXML - vamos apenas exibir o conteúdo do arquivo Projetos.xml e para isso vamos incluir no evento Click do botão de comando - Acessar e Ler Arquivo XML - o código abaixo:

 private void btnLerXML_Click(object sender, EventArgs e)
 {
            try
            {
                XmlTextReader reader = new XmlTextReader(@"..\..\Projetos.xml");
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element: // O nó é um elemento
                            lbXML.Items.Add("<" + reader.Name + ">");
                            if (reader.HasAttributes)
                            {
                                while (reader.MoveToNextAttribute())
                                {
                                    //Pega o valor do atributo.
                                    lbXML.Items.Add(reader.Value);
                                }
                            }
                            break;
                        case XmlNodeType.Text: //Exibe o texto em cada elemento
                            lbXML.Items.Add(reader.Value);
                            break;
                        case XmlNodeType.EndElement: //Exibe o fim do elemento
                            lbXML.Items.Add("</" + reader.Name + ">");
                            break;
                    }
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("Erro : " + ex.Message);            
            }
}
 
Private Sub btnLerXML_Click(sender As Object, e As EventArgs)
           Try
		Dim reader As New XmlTextReader("..\..\Projetos.xml")
		While reader.Read()
			Select Case reader.NodeType
				Case XmlNodeType.Element
					' O nó é um elemento
					lbXML.Items.Add("<" + reader.Name + ">")
					If reader.HasAttributes Then
						While reader.MoveToNextAttribute()
							'Pega o valor do atributo.
							lbXML.Items.Add(reader.Value)
						End While
					End If
					Exit Select
				Case XmlNodeType.Text
					'Exibe o texto em cada elemento
					lbXML.Items.Add(reader.Value)
					Exit Select
				Case XmlNodeType.EndElement
					'Exibe o fim do elemento
					lbXML.Items.Add("</" + reader.Name + ">")
					Exit Select
			End Select
		End While
	Catch ex As Exception
		MessageBox.Show("Erro : " + ex.Message)
	End Try
End Sub
C# VB .NET

Este código irá ler e exibir o conteúdo do arquivo XML no controle Listbox.

Lendo XML Recursivamente

Vamos agora acessar informações do arquivo XML usando a recursão.

O que pretendemos e obter os funcionários alocados por projeto.

Para isso a interface fornece um controle Combobox - cboProjetos - contendo os projetos definidos no arquivo XML.

Quando o usuário selecionar um projeto no controle Combobox iremos usar o evento SelectedIndexChanged para carregar o arquivo XML e chamar o método LerXML() que por sua vez irá chamar o método FuncionariosPorProjeto e chamar a si mesma para obter os nomes dos funcionários para o projeto selecionado caracterizando assim a técnica da recursão.

Então no evento SelectedIndexChanged vamos incluir o código abaixo:

 private void cboProjetos_SelectedIndexChanged(object sender, EventArgs e)
 {
            txtFuncionariosProjeto.Text = "";
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load(@"../../Projetos.xml");
                XmlNode root = doc.SelectSingleNode("*");
                LerXML(root);
            }
            catch(Exception ex)
            {
                MessageBox.Show("Erro : " + ex.Message);
            }
 }
Private Sub cboProjetos_SelectedIndexChanged(sender As Object, e As EventArgs)
	txtFuncionariosProjeto.Text = ""
	Dim doc As New XmlDocument()
	Try
		doc.Load("../../Projetos.xml")
		Dim root As XmlNode = doc.SelectSingleNode("*")
		LerXML(root)
	Catch ex As Exception
		MessageBox.Show("Erro : " + ex.Message)
	End Try
End Sub

 

C# VB .NET

O código do método LerXML() é dado a seguir:

 private void LerXML(XmlNode root)
  {
            if (root is XmlElement)
            {
                FuncionariosPorProjeto(root);
                if (root.HasChildNodes)
                    LerXML(root.FirstChild);
                if (root.NextSibling != null)
                    LerXML(root.NextSibling);
            }
            else if (root is XmlText)
            { }
            else if (root is XmlComment)
            { }
 }
Private Sub LerXML(root As XmlNode)

	If TypeOf root Is XmlElement Then
		FuncionariosPorProjeto(root)
		If root.HasChildNodes Then
			LerXML(root.FirstChild)
		End If
		If root.NextSibling IsNot Nothing Then
			LerXML(root.NextSibling)
		End If
	ElseIf TypeOf root Is XmlText Then
	ElseIf TypeOf root Is XmlComment Then
	End If
End Sub
C# VB .NET

No método LerXML() vemos que para cada elemento do XML chamamos o método FuncionariosPorProjeto e a seguir, havendo nós filhos, chamamos recursivamente o método LerXML() novamente. 

O código do método FuncionariosPorProjeto  é dado abaixo:

private void FuncionariosPorProjeto(XmlNode node)
 {
     if (node.Attributes["Codigo"] != null)
         if (node.Name == "projeto" && node.Attributes["Codigo"].Value == cboProjetos.Text)
             txtFuncionariosProjeto.Text += node.ParentNode.ParentNode.Attributes["Nome"].Value + "\r\n";
 }
Private Sub FuncionariosPorProjeto(node As XmlNode)
   If node.Attributes("Codigo") IsNot Nothing Then
     If node.Name = "projeto" AndAlso node.Attributes("Codigo").Value = cboProjetos.Text Then
	txtFuncionariosProjeto.Text += node.ParentNode.ParentNode.Attributes("Nome").Value + vbCr & vbLf
     End If
   End If
End Sub
C# VB .NET

Este código irá obter o nome dos funcionários para o projeto selecionado na Combobox.

Agora podemos executar o projeto e verificar o resultado conforme abaixo:

Conclusão !

A recursividade é recurso poderoso que pode facilitar a vida do desenvolvedor mas deve ser usado com cuidado.

Pegue o projeto completo aqui: Lendo_XML_Recursivamente.zip

E Jesus, chamando um menino, o pôs no meio deles,
E disse: Em verdade vos digo que, se não vos converterdes e não vos fizerdes como meninos, de modo algum entrareis no reino dos céus.
Mateus 18:2,3

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti