Páginas

quarta-feira, 7 de abril de 2010

Lazarus - Criando XML a partir de um DataSet

Sabemos que um documento XML pode ser criado manipulando strings e arquivos texto. Esta opção não é aconselhável, pois é difícil garantir que o documento seja bem formado. A melhor forma de fazer isso é usar DOM (Modelo Objeto de Documento). Já usamos esse padrão para ler um documento XML no artigo anterior.
Para ilustrar a criação de um documento vamos implementar uma aplicação que gera um XML a partir dos registros de um DataSet. Para isso vamos usar nosso banco de dados SQLite de exemplos anteriores e vamos usar ZeosLib. Mas pode ser usado qualquer conjunto de componentes, inclusive SQLdb.
Coloque então um TZConnection no form, ou num Data Module. Defina a propriedade Database com o banco SQLite, ou qualquer outro. Defina a propriedade Protocol com sqlite-3.
Coloque também um TZReadOnlyQuery e defina Name como queCidade. Em Connection selecione o TZConnection. Na propriedade SQL digite SELECT * FROM CIDADE.
Insira um botão, que vai executar a criação do XML.

Na cláusula uses acrescente as units DOM e XMLWrite.

Agora vamos criar o código que efetivamente irá criar o XML. A idéia é criar um procedimento genérico, que servirá para qualquer tabela.
O procedimento Tabela2DOM() recebe como argumentos o nome do nó raiz, o nome do nó pai, o próprio documento XML e o DataSet. Observe o código abaixo:

procedure TfrmDataXml.Tabela2DOM(Raiz, Registro: string; XMLDoc: TXmlDocument; DataSet: TDataSet);
var
  iRaiz, iPai, iFilho: TDOMNode;
  i, j: Integer;
begin
  DataSet.Open;
  DataSet.First;
  iRaiz := XMLDoc.CreateElement(Raiz);
  XMLDoc.AppendChild(iRaiz);
  j := 0;
  while not DataSet.EOF do
  begin
    iRaiz := XMLDoc.DocumentElement;
    iPai := XMLDoc.CreateElement(Registro);
    iRaiz.AppendChild(iPai);
    for I := 0 to DataSet.FieldCount - 1 do
    begin
      if not (DataSet.Fields[i].IsNull) then
      begin
         iPai := XMLDoc.CreateElement(DataSet.Fields[i].FieldName);
         iFilho := XMLDoc.CreateTextNode(DataSet.Fields[i].AsString);
         iPai.AppendChild(iFilho);
         iRaiz.ChildNodes.Item[j].AppendChild(iPai);
      end;
    end;
    DataSet.Next;
    j := j + 1;
  end;
  DataSet.Close;
end;  

Nas linhas 8 e 9 criamos o nó raiz e o adicionamos ao documento. O método AppendChild() adiciona um nó ao documento.
A partir da linha 11 iniciamos a varredura da tabela. Para cada registro da tabela adicionamos um nó pai com o nome passado como parâmetro, que é feito nas linhas 14 e 15.
O for da linha 16 irá precorrer os campos de cada registro da tabela. Para cada registro criamos um nó pai com o nome do campo (linha 20) e um nó filho com o conteúdo do campo. A linha 18 evita a inclusão de campos vazios no documento.

No evento OnClick do botão criamos o objeto DOM, o procedimento acima é chamado, o documento é gravado usando o método writeXMLFile() e o objeto é destruido.

procedure TfrmDataXml.btnCriarClick(Sender: TObject);
begin
  XMLDoc := TXMLDocument.Create;
  Tabela2DOM ('cidades', 'cidade', XMLDoc, queCidade);
  writeXMLFile(XMLDoc,'cidade.xml');
  XMLdoc.free;
end;   

Para executar lembre de conectar o banco e abrir a tabela, conforme visto em artigos anteriores.
Baixe aqui o código completo do exemplo.

4 comentários:

Edson disse...

Por favor, onde consigo as units :

DOM,XMLRead e XMLWrite ?

Obs.: Trabalho com Delphi 7

Desde já agradeço,
Edson Clemente

Professor Carlos disse...

No Delphi tem um componente que faz tudo isso, o XMLDocument. Fica na paleta de componentes Internet. Veja ai se consegue e qualquer dúvida me escreva.

Edson disse...

Professor, eu já incluir o componente XMLDocument,pois somente as units:
xmldom, XMLIntf, msxmldom, XMLDoc foram acrescentadas no uses, as units DOM e XMLRead e XMLWrite não foram, pois na chama da procedure ReadXMLFile, do seu exemplo, o delphi não as reconhcece.

Agradeço muito a atenção,
Edson Clemente

Professor Carlos disse...

Pra ler use o método LoadFromFile() e pra salvar use SaveToFile(). Ambos são do componente. XMLRead e XMLWrite são apenas do lazarus. Lazarus ainda não tem um componente como Delphi,por isso implementa através dessas três units.
Não tente fazer em Delphi usando o código do meu artigo. Existem algumas diferenças. Veja esse artigo aqui:
http://www.caiooliveira.com.br/?p=73

 
Creative Commons License
This work by Carlos Alberto P. Araújo is licensed under a Creative Commons Atribuição-Uso não-comercial-Compartilhamento pela mesma licença 3.0 Brasil License.