Ir para conteúdo
Faça parte da equipe! (2024) ×

Usando arquivos XML no formato simples


denwc
 Compartilhar

Posts Recomendados

Olá pessoal, muitos de vocês que estão começando em .NET e vieram do Visual Basic 6.0 procuram pela API que permite gravar e ler arquivos .INI. Usávamos este tipo de arquivo no VB6 pois eram a melhor e mais fácil alternativa para guardar configurações de usuário para os nossos aplicativos.

 

Em C#.NET temos uma vasta biblioteca que fazem este tipo de serviço BEM mais fácil. Então eu decidi mostrar uma classe que eu desenvolvi durante meu aprendizado para salvar e ler configurações de arquivos XML básicos (quando eu digo básico, quero dizer que não tem muitas estruturas).

Vejamos o que seria um arquivo básico:

 

<?xml version="1.0" encoding="utf-8"?>

<CONFIG>

<Comum>

<!-- atualizadoem DEVE ser a primeira chave deste grupo!!!-->

<ATUALIZADOEM required="1">19/01/2011 15:00</ATUALIZADOEM>

<drvTemplates required="1">\\10.32.8.1\FERRAMENTAS\Templates\Aprovados\</drvTemplates>

<BD_DATASOURCE required="1">db554-srv001</BD_DATASOURCE>

<BDCOLAB_DATASOURCE required="1">ww553-wrk002</BDCOLAB_DATASOURCE>

<extensao required="1">.xls</extensao>

<picmaxHei required="1">700</picmaxHei>

<picmaxWid>486</picmaxWid>

<lastUser>12345678</lastUser>

<showexcel>false</showexcel>

</Comum>

</CONFIG>

 

Tabela 1 – Conteúdo exemplo do arquivo XML

 

A classe que criei abaixo faz o controle do arquivo acima. Para isto você verá que vamos usar o SYSTEM.XML.LINQ. Esta classe nos traz muita facilidade para mecher com arquivos do tipo XML.

 

O código completo da classe clXML está abaixo.

 

A biblioteca KaiserSoft.Facilities é uma outra classe que eu criei que contém métodos estáticos que são usados sempre e por vários aplicativos mas que para esta classe XML não tem importância, então, onde você encontrar no código (clFacilidades.Reportprg) pode apagar pois é só um log e onde você encontrar (clFacilidades.Reportprg), pode trocar por MessageBox.Show(“....”);

 

using System;

using System.Collections.Generic;

using System.Xml.Linq;

using KaiserSoft.Facilities;

 

namespace System

{

class clXML

{

private XDocument xmlDoc = null;

private bool arquivoAberto;

private string Arquivo;

 

public clXML()

{

clFacilidades.Reportprg("clXML", "clXML", "Constructor");

xmlDoc = new XDocument();

}

~clXML()

{

clFacilidades.Reportprg("clXML", "~clXML", "Destructor");

// o destrutor está aqui para fechar o arquivo aberto, assim o usuario não precisa chamar nenhum passo para fazer isto

xmlDoc = null;

arquivoAberto = false;

}

 

public void Dispose()

{

clFacilidades.Reportprg("clXML", "Dispose", "");

 

xmlDoc = null;

arquivoAberto = false;

}

 

private bool OpenFile(string Arq)

{

clFacilidades.Reportprg("clXML", "OpenFile", @Arq);

if (!arquivoAberto)

{

Arquivo = Arq;

arquivoAberto = true;

try

{

xmlDoc = XDocument.Load(Arq);

}

catch (Exception ex)

{

clFacilidades.Report("Erro ao abrir o arquivo XML: " + Arq, "clXML", "OpenFile", ex.Message.ToString());

arquivoAberto = false;

}

}

return arquivoAberto;

}

 

public string getValue(string Group, string Key)

{

clFacilidades.Reportprg("clXML", "getValue", "Group,Key");

if (!arquivoAberto)

return "";

 

try

{

return xmlDoc.Root.Element(Group).Element(Key).Value.ToString();

}

catch (Exception)

{

return "";

}

 

}

public string getValue(string Group, string Key, string Arq)

{

clFacilidades.Reportprg("clXML", "getValue", "Arq:" + Arq);

// chamar esta rotina na primeira vez, depois usar somente getValue

if (arquivoAberto)

{

xmlDoc = null;

arquivoAberto = false;

}

if (OpenFile(Arq) == false)

return "";

 

return getValue(Group,Key);

}

public bool getNextNode(string Group, ref string Key, ref string Value, ref string Attrib)

{

clFacilidades.Reportprg("clXML", "getNextNode", "G:" + Group + " V:" + Value + "A:" + Value);

XElement no;

if (!arquivoAberto)

{

clFacilidades.Report("O arquivo XML não foi aberto ainda!", "clXML", "getNextNode", "Attrib");

Attrib = "";

return true;

}

if (Key == string.Empty)

{

// pega a primeira chave disponível dentro deste grupo

no = null;

}

else

no = (XElement)xmlDoc.Root.Element(Group).Element(Key).NextNode;

 

Attrib = Value = "";

if (no != null)

{

Key = no.Name.ToString();

if (no.HasAttributes)

{

Attrib = no.Attribute("required").Value.ToString();

Value = no.Value.ToString();

}

}

else

return true; // acabaram os nós

 

return false;

}

public bool getNextNode(string Group, ref string Key, ref string Value)

{

clFacilidades.Reportprg("clXML", "getNextNode", "G:" + Group + " Value:" + Value);

XElement no;

if (!arquivoAberto)

{

clFacilidades.Report("O arquivo XML não foi aberto ainda!", "clXML", "getNextNode", "");

return true;

}

if (Key == string.Empty)

{

// pega a primeira chave disponível dentro deste grupo

no = null;

}

else

no = (XElement)xmlDoc.Root.Element(Group).Element(Key).NextNode;

 

Value = "";

if (no != null)

{

Key = no.Name.ToString();

Value = no.Value.ToString();

}

else

return true; // acabaram os nós

return false;

}

 

public void setValue(string Group, string Key, string Value, string Arq)

{

clFacilidades.Reportprg("clXML", "setValue", "Arq:" + Arq);

if (!arquivoAberto)

if (OpenFile(Arq) == false)

return;

 

setValue(Group, Key, Value);

}

public void setValue(string Group, string Key, string Value)

{

clFacilidades.Reportprg("clXML", "setValue", "Group,Key,Value");

// precisa verificar se o grupo existe, senão cria ele

if (CreateGroup(Group, Key, Value))

{

xmlDoc.Root.Element(Group).Element(Key).Value = Value;

}

}

 

public bool CreateGroup(string Group, string Key, string Value)

{

clFacilidades.Reportprg("clXML", "createGroup", "Grupo:" + Group);

if (!arquivoAberto)

return false;

 

string txt;

 

try

{

txt = xmlDoc.Root.Element(Group).Name.ToString();

}

catch (Exception)

{

xmlDoc.Root.Add(new XElement(Group, new XElement(Key,Value))); // cria o grupo e já cria a Key

return false;

}

 

// neste ponto, o Grupo existe, porém a Key pode ser nova

try

{

txt = xmlDoc.Root.Element(Group).Element(Key).Name.ToString();

}

catch (Exception)

{

//xmlDoc.Root.Add(xmlDoc.Root.Element(Group), new XElement(Key, Value));

xmlDoc.Root.Element(Group).Add(new XElement(Key, Value));

return false;

}

// neste ponto, o grupo existe e a key também, então informa que precisa só escrever o valor

return true;

}

 

public bool saveFile(string SaveAs)

{

clFacilidades.Reportprg("clXML", "saveFile", "SaveAs=" + SaveAs);

 

try

{

if (SaveAs != string.Empty)

xmlDoc.Save(@SaveAs);

else

xmlDoc.Save(@Arquivo);

}

catch (Exception ex)

{

clFacilidades.Report("Erro ao salvar o arquivo XML", "clXML", "saveFile", ex.Message.ToString());

return false;

}

return true;

}

 

}

}

 

Tabela 2 – Código fonte da classe clXML

 

Como usar a classe acima:

 

Para utilizar a classe acima, aqui vai um bom exemplo. Na rotina de start-up do seu aplicativo (normalmente em algum form_Load), vamos colocar o código abaixo.

 

NOTA: Perceba que a rotina abaixo faz uso da parte de Settings do seu projeto, então você precisa criar as chaves nesta configuração para que a rotina possa ler e armazenar os valores.

 

Explicando o que ele faz:

 

Quando o aplicativo é instalado, o arquivo config.xml (que faz parte do pacote de instalação), é copiado por cima do arquivo onde o aplicativo foi instalado.

 

Ao executar o seu aplicativo, a rotina abaixo vai comparar as diferenças entre este arquivo novo e o arquivo que se encontra no diretório de documentos do aplicativo (este diretório é criado automaticamente caso não exista e o arquivo config.xml novo é copiado dentro dele), que fica no Documents and Settings\NomedoAplicativo

 

Sempre que seu instalador for modificado, o arquivo config.xml é copiado novametne e a rotina abaixo só vai copiar os dados que estiverem marcados como required. Isto significa que, por exemplo, o último usuário que logou no sistema não será sobrescrito, apenas serão sobrescritos os dados que você marcou como dados que o programa depende para funcionar e que o usuário normalmente não altera (required=”1”). Desta forma, se a localização do banco de dados foi alterada, por exemplo, na próxima instalação este dado será atualizado automaticamente.

 

#region CONFIG.XML

float a;

bool b;

 

clXML xml = new clXML();

clXML xml2 = new clXML();

string txt1, txt2 = "";

Properties.Settings.Default.drvProgramData = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + System.Windows.Forms.Application.ProductName + "\\";

 

// verifica se a data do config.xml instalado é <> do que o do usuário, se sim, copia por cima o arquivo

txt1 = xml2.getValue("Comum", "ATUALIZADOEM", Properties.Settings.Default.drv + "Config.xml");

txt2 = xml.getValue("Comum", "ATUALIZADOEM", Properties.Settings.Default.drvProgramData + "Config.xml");

if (txt1 != txt2)

{

// cria a pasta

try

{

Directory.CreateDirectory(Properties.Settings.Default.drvProgramData);

// se o arquivo ainda não existe, então só copia o novo

if (!File.Exists(Properties.Settings.Default.drvProgramData + "Config.xml"))

File.Copy(Properties.Settings.Default.drv + "Config.xml", Properties.Settings.Default.drvProgramData + "Config.xml", true);

else

{

// como o arquivo já existe, então copia somente as chaves dentro de comum que contiverem o atributo de obrigatório

string Key = "ATUALIZADOEM";

string Value = "";

string Attrib = "";

// já grava a primeira informação que é a data

xml.setValue("Comum", Key, txt1);

while (!xml2.getNextNode("Comum", ref Key, ref Value, ref Attrib))

{

// se Key = "" é porque esta chave não contém o atributo de cópia obrigatória, então não copia

if (Attrib != "") xml.setValue("Comum", Key, Value);

}

xml.saveFile("");

}

 

}

catch (Exception ex)

{

MessageBox.Show(ex.Message.ToString(), "Erro ao copiar arquivo de definições!");

this.Dispose();

return;

}

}

xml2.Dispose();

#endregion

 

// pega a localização do servidor de banco de dados

txt1 = "";

txt1 = xml.getValue("Comum", "BD_DATASOURCE", Properties.Settings.Default.drvProgramData + "Config.xml");

if (txt1 != "") Properties.Settings.Default.BD_DATASOURCE = txt1;

string lastUser = xml.getValue("Comum", "lastUser");

txt1 = xml.getValue("Comum", "drvTemplates");

if (txt1 != "") Properties.Settings.Default.drvTemplates = txt1 +System.Windows.Forms.Application.ProductName + "\\";

txt1 = xml.getValue("Comum", "picmaxWid");

float.TryParse(txt1, out a);

Properties.Settings.Default.picmaxWid = a;

txt1 = xml.getValue("Comum", "picmaxHei");

float.TryParse(txt1, out a);

Properties.Settings.Default.picmaxHei = a;

txt1 = xml.getValue("Comum", "extensao");

if (txt1 != "") Properties.Settings.Default.extensao = txt1;

txt1 = xml.getValue("Comum", "showexcel");

bool.TryParse(txt1, out b);

if (txt1 != "") Properties.Settings.Default.showExcel = b;

xml.Dispose();

xml = null;

 

 

 

Tabela 3 – Exemplo de leitura dos dados do arquivo XML

E agora, um exemplo de como salvar uma informação (desde que não seja required), no arquivo XML:

 

// SALVA ULTIMO USUÁRIO LOGADO

xml = new clXML();

xml.setValue("Comum", "lastUser", Properties.Settings.Default.userlogin, Properties.Settings.Default.drvProgramData + "Config.xml");

xml.setValue("Comum", "appdrv", Application.ExecutablePath);

xml.saveFile("");

xml.Dispose();

xml = null;

 

Tabela 4 – Exemplo de escrita de dados no arquivo XML

 

Note que no exemplo da tabela 4, o programa está mandando salvar o valor para o campo appdrv. Se você notar no arquivo XML da tabela 1, este campo não existe. Neste caso a classe clXML vai se encarregar de criar o campo e colocar seu valor. Isto é válido também se você mudar o grupo “Comum” para outro nome, a classe se encarrega de criar o grupo caso ele não exista, evitando erros.

 

Este é o final do nosso artigo. A classe clXML acima será utilizada em outros artigos que eu venha a postar, então guarde-a com carinho.

 

look_by_denwc-d4wlgc0.png

Link para o comentário
Compartilhar em outros sites

Este tópico está impedido de receber novos posts.
 Compartilhar

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.