Difference between revisions of "XML Tutorial/pt"
(→Introdução: - Update translation) |
m (Fixed syntax highlighting) |
||
(9 intermediate revisions by 3 users not shown) | |||
Line 7: | Line 7: | ||
Atualmente há um conjunto de units que fornecem suporte para o XML no Free Pascal. Estas units são chamadas "XMLRead", "XMLWrite" e "DOM" e elas são parte da Biblioteca de Componentes Livre (FCL) do compilador Free Pascal. A FCL já esta presente no caminho de busca (search path) padrão para o compilador no Lazarus, assim você só precisa adicionar as units na claúsula uses para ter suporte ao XML. A FCL não está com sua documentação atualizada (Outubro/2005), assim este pequeno tutorial é uma introdução ao acesso a XML usando estas units. | Atualmente há um conjunto de units que fornecem suporte para o XML no Free Pascal. Estas units são chamadas "XMLRead", "XMLWrite" e "DOM" e elas são parte da Biblioteca de Componentes Livre (FCL) do compilador Free Pascal. A FCL já esta presente no caminho de busca (search path) padrão para o compilador no Lazarus, assim você só precisa adicionar as units na claúsula uses para ter suporte ao XML. A FCL não está com sua documentação atualizada (Outubro/2005), assim este pequeno tutorial é uma introdução ao acesso a XML usando estas units. | ||
− | O XML DOM (Modelo Objeto de Documento) é um conjunto objetos padronizados que fornece uma interface similar para uso em diferentes linguagens e sistemas. O padrão só especifica os métodos, propriedades e outras partes da interface do objeto, deixando a implementação liberada para diferentes linguagens. A FCL atualmente tem suporte completo a [http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/ | + | O XML DOM (Modelo Objeto de Documento) é um conjunto objetos padronizados que fornece uma interface similar para uso em diferentes linguagens e sistemas. O padrão só especifica os métodos, propriedades e outras partes da interface do objeto, deixando a implementação liberada para diferentes linguagens. A FCL atualmente tem suporte completo a [http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/ XML DOM 1.0]. |
− | == | + | == Exemplos == |
− | + | A seguir tem uma lista de exemplos de manipulação de dados XML com complexidade crescente. | |
− | <xml> | + | === Lendo um nó de texto (text node) === |
+ | |||
+ | Para programadores Delphi: | ||
+ | Note que, quando trabalha-se com TXMLDocument, o texto dentro de um Nó é considerado um nó de TEXTO separado. Como resultado, você deve acessar o valor do | ||
+ | |||
+ | texto do nó como um nó separado. Como alternativa, a propriedade '''TextContent''' pode ser usada para extrair o conteúdo de todos os nós de textos abaixo do | ||
+ | |||
+ | nó dado, com ambos concatenados. | ||
+ | |||
+ | A procedure '''ReadXMLFile''' sempre cria um novo '''TXMLDocument''', assim você não tem que criá-lo com antecedência. Entretanto, tenha certeza de destruir | ||
+ | |||
+ | o documento chamando '''Free''' quando você terminar. | ||
+ | |||
+ | Por exemplo, considere o seguinte XML: | ||
+ | |||
+ | <syntaxhighlight lang="xml"> | ||
+ | <?xml version="1.0"?> | ||
+ | <request> | ||
+ | <request_type>PUT_FILE</request_type> | ||
+ | <username>123</username> | ||
+ | <password>abc</password> | ||
+ | </request> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | O seguinte exemplo de código mostra ambas as formas (correta e incorreta) de pegar o valor do nó de texto: | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | var | ||
+ | PassNode: TDOMNode; | ||
+ | Doc: TXMLDocument; | ||
+ | begin | ||
+ | // Lê no arquivo xml no disco | ||
+ | ReadXMLFile(Doc, 'c:\xmlfiles\test.xml'); | ||
+ | // Extrai o nó "password" | ||
+ | PassNode := Doc.DocumentElement.FindNode('password'); | ||
+ | // Escreve por extenso o valor do nó selecionado | ||
+ | WriteLn(PassNode.NodeValue); // estará em branco | ||
+ | // O texto do nó é atualmente um "nó filho" separado | ||
+ | WriteLn(PassNode.FirstChild.NodeValue); // mostra corretamente "abc" | ||
+ | // como alternativa | ||
+ | WriteLn(PassNode.TextContent); | ||
+ | // finalmente, libera o documento | ||
+ | Doc.Free; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Mostrando os nomes dos nós === | ||
+ | |||
+ | Uma nota rápida na navegação pela árvore DOM: Quando você precisar acessar nós em seqüencia, é melhor usar as propriedades '''FirstChild''' e | ||
+ | |||
+ | '''NextSibling''' (para métodos '''GetElementsByTagName''', mas esses serão criados um objeto TDOMNodeList que deverá ser eventualmente liberado. Isso difere | ||
+ | |||
+ | das outras implementações DOM como MSXML, porque a implementação feita pela FCL é baseada em objeto, não baseada na interface (interface-based). | ||
+ | |||
+ | Os seguintes exemplos demonstram como mostrar os nomes dos nodes para um TMemo localizado em um formulário. | ||
+ | |||
+ | A seguir o arquivo XML chamado 'C:\Programas\teste.xml': | ||
+ | |||
+ | <syntaxhighlight lang="xml"> | ||
<?xml version="1.0"?> | <?xml version="1.0"?> | ||
<images directory="mydir"> | <images directory="mydir"> | ||
Line 21: | Line 79: | ||
</imageNode> | </imageNode> | ||
</images> | </images> | ||
− | </ | + | </syntaxhighlight> |
− | + | E aqui o código Pascal para executar a tarefa: | |
− | < | + | <syntaxhighlight lang=pascal> |
var | var | ||
− | + | Documento: TXMLDocument; | |
− | + | Child: TDOMNode; | |
+ | j: Integer; | ||
begin | begin | ||
− | + | ReadXMLFile(Documento, 'C:\Programas\teste.xml'); | |
− | + | Memo.Lines.Clear; | |
− | + | // usando as propriedades FirstChild e NextSibling | |
+ | Child := Documento.DocumentElement.FirstChild; | ||
+ | while Assigned(Child) do | ||
+ | begin | ||
+ | Memo.Lines.Add(Child.NodeName + ' ' + Child.Attributes.Item[0].NodeValue); | ||
+ | // usando método ChildNodes | ||
+ | with Child.ChildNodes do | ||
+ | try | ||
+ | for j := 0 to (Count - 1) do | ||
+ | Memo.Lines.Add(Item[j].NodeName + ' ' + Item[j].FirstChild.NodeValue); | ||
+ | finally | ||
+ | Free; | ||
+ | end; | ||
+ | Child := Child.NextSibling; | ||
+ | end; | ||
+ | Documento.Free; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Isso mostrará: | ||
+ | |||
+ | <pre> | ||
+ | imageNode graphic.jpg | ||
+ | Peca Pecacastelo.jpg1.swf | ||
+ | Peca Pecacastelo.jpg1.swf | ||
+ | </pre> | ||
+ | |||
+ | === Povoando um TreeView com XML === | ||
+ | |||
+ | Um uso comum de arquivos XML é analisá-los e mostrar seu conteúdo em uma árvore como formato. Você pode encontrar o componente TTreeView na aba/guia "Common | ||
+ | |||
+ | Controls" do Lazarus. | ||
+ | |||
+ | A função a seguir pegará um documento XML, previamente carregado de um arquivo ou genrado em código, e povoará um TreeView com seu conteúdo. O ''caption'' de | ||
+ | |||
+ | cada nó consistirá no conteúdo do primeiro atributo de cada nó. | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument); | ||
+ | var | ||
+ | iNode: TDOMNode; | ||
+ | |||
+ | procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode); | ||
+ | var | ||
+ | cNode: TDOMNode; | ||
begin | begin | ||
− | + | if Node = nil then Exit; // Pára, se atingir a folha | |
+ | |||
+ | // Adiciona um nó para a árvore | ||
+ | TreeNode := tree.Items.AddChild(TreeNode, Node.Attributes[0].NodeValue); | ||
+ | |||
+ | // Vai para o primeiro nó filho | ||
+ | cNode := Node.FirstChild; | ||
+ | |||
+ | // Processa todos os nós filhos | ||
+ | while cNode <> nil do | ||
begin | begin | ||
− | + | ProcessNode(cNode, TreeNode); | |
− | + | cNode := cNode.NextSibling; | |
− | |||
− | |||
− | |||
− | |||
end; | end; | ||
end; | end; | ||
− | Documento.Free; | + | |
− | end; | + | begin |
− | </ | + | iNode := XMLDoc.DocumentElement.FirstChild; |
+ | while iNode <> nil do | ||
+ | begin | ||
+ | ProcessNode(iNode, nil); // Recursivo | ||
+ | iNode := iNode.NextSibling; | ||
+ | end; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Modificando um documento XML === | ||
+ | |||
+ | A primeira coisa a ser lembrada é que TDOMDocumento é o "handle" para o DOM. Você pode pegar uma instância dessa classe criando uma ou carregando um | ||
+ | |||
+ | documento XML. | ||
+ | |||
+ | Nós, por outro lado, não podem ser criados como um objeto normal. Você *deve* usar os métodos fornecidos por TDOMDocumento para criá-los, e posteriormente | ||
+ | |||
+ | usar outros métodos para colocá-los no lugar correto na árvore. Isso ocorre porque os nós devem ser "pertencentes" a um documento específico no DOM. | ||
+ | |||
+ | A seguir alguns métodos comuns de TDOMDocument: | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | function CreateElement(const tagName: DOMString): TDOMElement; virtual; | ||
+ | function CreateTextNode(const data: DOMString): TDOMText; | ||
+ | function CreateCDATASection(const data: DOMString): TDOMCDATASection; | ||
+ | virtual; | ||
+ | function CreateAttribute(const name: DOMString): TDOMAttr; virtual; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | E aqui um método de exemplo que localizará o item selelcionado em um TTreeView e inseri-rá um nó filho para o documento XML que ele representa. O TreeView | ||
+ | |||
+ | deve ser previamente preenchido com o conteúdo de um arquivo XML usando a [[Networking#Populating a TreeView with XML|função XML2Tree]]. | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | procedure TForm1.actAddChildNode(Sender: TObject); | ||
+ | var | ||
+ | Posicao: Integer; | ||
+ | NovoNo: TDomNode; | ||
+ | begin | ||
+ | {******************************************************************* | ||
+ | * Detecta o elemento selecionado | ||
+ | *******************************************************************} | ||
+ | if TreeView1.Selected = nil then Exit; | ||
+ | |||
+ | if TreeView1.Selected.Level = 0 then | ||
+ | begin | ||
+ | Posicao := TreeView1.Selected.Index; | ||
+ | |||
+ | NovoNo := XMLDoc.CreateElement('item'); | ||
+ | TDOMElement(NovoNo).SetAttribute('nome', 'Item'); | ||
+ | TDOMElement(NovoNo).SetAttribute('arquivo', 'Arquivo'); | ||
+ | with XMLDoc.DocumentElement.ChildNodes do | ||
+ | begin | ||
+ | Item[Posicao].AppendChild(NovoNo); | ||
+ | Free; | ||
+ | end; | ||
+ | |||
+ | {******************************************************************* | ||
+ | * Atualiza o TreeView | ||
+ | *******************************************************************} | ||
+ | TreeView1.Items.Clear; | ||
+ | XML2Tree(TreeView1, XMLDoc); | ||
+ | end | ||
+ | else if TreeView1.Selected.Level >= 1 then | ||
+ | begin | ||
+ | {******************************************************************* | ||
+ | * Essa função funciona somente no primeiro nível da árvore, | ||
+ | * mas pode facilmente ser modificada para funcionar em quaisquer outros níveis | ||
+ | *******************************************************************} | ||
+ | end; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Criar um TXMLDocument de um string === | ||
+ | |||
+ | Dado um arquivo XML em MyXmlString, o seguinte código criará esse DOM: | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | Var | ||
+ | S : TStringStream; | ||
+ | XML : TXMLDocument; | ||
+ | |||
+ | begin | ||
+ | S:= TStringStream.Create(MyXMLString); | ||
+ | Try | ||
+ | S.Position:=0; | ||
+ | XML:=Nil; | ||
+ | ReadXMLFile(XML,S); // Completa o documento XML | ||
+ | // Alternativamente: | ||
+ | ReadXMLFragment(AParentNode,S); // Lê somente um fragmento XML. | ||
+ | Finally | ||
+ | S.Free; | ||
+ | end; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Validando um documento === | ||
+ | |||
+ | Desde Março de 2007, ''DTD validation facility'' foi adicionado para o analisador XML da FCL. A validação é a verificação da estrutura lógica do documento | ||
+ | |||
+ | conforme as regras pré-definidas, chamadas ''Documento Type Definition'' (DTD). | ||
+ | |||
+ | Aqui está um exemplo de um documento XML com um DTD: | ||
+ | |||
+ | <syntaxhighlight lang="xml"> | ||
+ | <?xml version='1.0'?> | ||
+ | <!DOCTYPE root [ | ||
+ | <!ELEMENT root (child)+ > | ||
+ | <!ELEMENT child (#PCDATA)> | ||
+ | ]> | ||
+ | <root> | ||
+ | <child>This is a first child.</child> | ||
+ | <child>And this is the second one.</child> | ||
+ | </root> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Esse DTD especifica que o elemento 'root' (raiz) deve ter um ou mais elementos 'child' (filho), e que os elementos 'child' pode ter somente dados de | ||
+ | |||
+ | caractere dentro. Se a análise deteca quaisquer violação dessas regras, ela reportará essas violações. | ||
+ | |||
+ | Carregar o documento dessa forma é um pouco mais complicado. Assumiremos que temos dados XML em um objeto TStream: | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | procedure TMyObject.DOMFromStream(AStream: TStream); | ||
+ | var | ||
+ | Parser: TDOMParser; | ||
+ | Src: TXMLInputSource; | ||
+ | TheDoc: TXMLDocument; | ||
+ | begin | ||
+ | // cria um objeto analisador | ||
+ | Parser := TDOMParser.Create; | ||
+ | // e a fonte de entrada | ||
+ | Src := TXMLInputSource.Create(AStream); | ||
+ | // nós queremos a validação | ||
+ | Parser.Options.Validate := True; | ||
+ | // associa um manipulador de erro que receberá as notificações | ||
+ | Parser.OnError := @ErrorHandler; | ||
+ | // agora faz o trabalho | ||
+ | Parser.Parse(Src, TheDoc); | ||
+ | // ...e limpeza total | ||
+ | Src.Free; | ||
+ | Parser.Free; | ||
+ | end; | ||
+ | |||
+ | procedure TMyObject.ErrorHandler(E: EXMLReadError); | ||
+ | begin | ||
+ | if E.Severity = esError then // nós estamos interessados somente em erros de validação | ||
+ | writeln(E.Message); | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Gerando um arquivo XML === | ||
+ | |||
+ | Abaixo um código completo para escrever em arquivo XML. | ||
+ | Você pode ler o tutorial completo no blog da DeveLazarus (veja [[XML_Tutorial/pt#Links Externos|Links Externos]]) | ||
+ | Por favor, lembre das bibliotecas DOM e XMLWrite na cláusula uses | ||
+ | |||
+ | <syntaxhighlight lang=pascal> | ||
+ | unit Unit1; | ||
− | + | {$mode objfpc}{$H+} | |
− | |||
− | + | interface | |
− | |||
− | |||
− | |||
− | + | uses | |
− | Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DOM, XMLWrite | + | Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, |
+ | DOM, XMLWrite; | ||
− | + | type | |
{ TForm1 } | { TForm1 } | ||
TForm1 = class(TForm) | TForm1 = class(TForm) | ||
Line 70: | Line 333: | ||
public | public | ||
{ public declarations } | { public declarations } | ||
− | end; | + | end; |
− | + | ||
− | Form1: TForm1; | + | var |
− | + | Form1: TForm1; | |
− | + | ||
+ | implementation | ||
+ | |||
+ | { TForm1 } | ||
− | + | procedure TForm1.Button1Click(Sender: TObject); | |
− | + | var | |
− | + | xdoc: TXMLDocument; // variável para o documento | |
− | + | noraiz, nopai, nofilho: TDOMNode; // variáveis dos nós | |
+ | begin | ||
+ | //cria um documento | ||
+ | xdoc := TXMLDocument.create; | ||
− | + | //cria nó raiz | |
+ | noraiz := xdoc.CreateElement('cadastro'); | ||
+ | Xdoc.Appendchild(noraiz); // salva nó raiz | ||
− | + | //cria nó pai | |
− | + | noraiz:= xdoc.DocumentElement; | |
+ | nopai := xdoc.CreateElement('usuario'); | ||
+ | TDOMElement(nopai).SetAttribute('id', '001'); // cria atributo para o nó pai | ||
+ | noraiz.Appendchild(nopai); // salva o nó pai | ||
− | + | //cria nó filho | |
− | + | nopai := xdoc.CreateElement('nome'); // cria o nó filho | |
− | + | //TDOMElement(nopai).SetAttribute('sexo', 'M'); // cria atributo | |
+ | nofilho := xdoc.CreateTextNode('Fernando'); // insere um valor para o nó | ||
+ | nopai.Appendchild(nofilho); // salva nó | ||
+ | noraiz.ChildNodes.Item[0].AppendChild(nopai); // insere o nó filho no nó pai correspondente | ||
− | + | //cria nó filho | |
− | + | nopai := xdoc.CreateElement('idade'); // cria nó filho | |
− | + | //TDOMElement(nopai).SetAttribute('ano', '1976'); // cria atributo | |
− | + | nofilho := xdoc.CreateTextNode('32'); // coloca um valor ao nó | |
− | + | nopai.Appendchild(nofilho); // salva o nó | |
+ | noraiz.ChildNodes.Item[0].AppendChild(nopai); // insere o nó filho no nó pai correspondente | ||
− | + | writeXMLFile(xDoc,'teste.xml'); // escreve o XML | |
− | + | Xdoc.free; // libera memória | |
− | + | end; | |
− | |||
− | |||
− | |||
− | + | initialization | |
− | + | {$I unit1.lrs} | |
− | |||
− | |||
− | |||
− | |||
− | + | end. | |
− | + | </syntaxhighlight> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | </ | ||
− | Resulta | + | Resulta no seguinte arquivo XML: |
− | <xml> | + | <syntaxhighlight lang="xml"> |
− | + | <?xml version="1.0" ?> | |
− | + | - <cadastro> | |
− | + | - <usuario id="001"> | |
− | + | <nome>Fernando</nome> | |
− | + | <idade>32</idade> | |
− | + | </usuario> | |
− | + | </cadastro> | |
− | </ | + | </syntaxhighlight> |
− | |||
− | |||
− | |||
--[[User:Fernandosinesio|Fernandosinesio]] 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com | --[[User:Fernandosinesio|Fernandosinesio]] 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com | ||
+ | |||
+ | == Links Externos == | ||
+ | |||
+ | * [http://www.w3schools.com/xml/default.asp W3Schools] Tutorial Xml | ||
+ | |||
+ | * [http://www.thomas-zastrow.de/texte/fpcxml/index.php Thomas Zastrow article] FPC e XML | ||
+ | |||
+ | * [http://develazarus.wordpress.com/2007/07/12/generando-un-archivo-xml/ Gerando um arquivo XML (Espanhol)] |
Latest revision as of 03:49, 2 March 2020
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
magyar (hu) │
Bahasa Indonesia (id) │
italiano (it) │
日本語 (ja) │
한국어 (ko) │
português (pt) │
русский (ru) │
中文(中国大陆) (zh_CN) │
Introdução
A "Extensible Markup Language" é uma linguagem recomendada pela W3C criada para a troca de informações entre diferentes sistemas. É um formato baseado em texto para armazenar informações. Linguagens modernas de troca de dados, como XHTML, bem como a maioria das tecnologia de WebServices, são baseados no XML.
Atualmente há um conjunto de units que fornecem suporte para o XML no Free Pascal. Estas units são chamadas "XMLRead", "XMLWrite" e "DOM" e elas são parte da Biblioteca de Componentes Livre (FCL) do compilador Free Pascal. A FCL já esta presente no caminho de busca (search path) padrão para o compilador no Lazarus, assim você só precisa adicionar as units na claúsula uses para ter suporte ao XML. A FCL não está com sua documentação atualizada (Outubro/2005), assim este pequeno tutorial é uma introdução ao acesso a XML usando estas units.
O XML DOM (Modelo Objeto de Documento) é um conjunto objetos padronizados que fornece uma interface similar para uso em diferentes linguagens e sistemas. O padrão só especifica os métodos, propriedades e outras partes da interface do objeto, deixando a implementação liberada para diferentes linguagens. A FCL atualmente tem suporte completo a XML DOM 1.0.
Exemplos
A seguir tem uma lista de exemplos de manipulação de dados XML com complexidade crescente.
Lendo um nó de texto (text node)
Para programadores Delphi: Note que, quando trabalha-se com TXMLDocument, o texto dentro de um Nó é considerado um nó de TEXTO separado. Como resultado, você deve acessar o valor do
texto do nó como um nó separado. Como alternativa, a propriedade TextContent pode ser usada para extrair o conteúdo de todos os nós de textos abaixo do
nó dado, com ambos concatenados.
A procedure ReadXMLFile sempre cria um novo TXMLDocument, assim você não tem que criá-lo com antecedência. Entretanto, tenha certeza de destruir
o documento chamando Free quando você terminar.
Por exemplo, considere o seguinte XML:
<?xml version="1.0"?>
<request>
<request_type>PUT_FILE</request_type>
<username>123</username>
<password>abc</password>
</request>
O seguinte exemplo de código mostra ambas as formas (correta e incorreta) de pegar o valor do nó de texto:
var
PassNode: TDOMNode;
Doc: TXMLDocument;
begin
// Lê no arquivo xml no disco
ReadXMLFile(Doc, 'c:\xmlfiles\test.xml');
// Extrai o nó "password"
PassNode := Doc.DocumentElement.FindNode('password');
// Escreve por extenso o valor do nó selecionado
WriteLn(PassNode.NodeValue); // estará em branco
// O texto do nó é atualmente um "nó filho" separado
WriteLn(PassNode.FirstChild.NodeValue); // mostra corretamente "abc"
// como alternativa
WriteLn(PassNode.TextContent);
// finalmente, libera o documento
Doc.Free;
end;
Mostrando os nomes dos nós
Uma nota rápida na navegação pela árvore DOM: Quando você precisar acessar nós em seqüencia, é melhor usar as propriedades FirstChild e
NextSibling (para métodos GetElementsByTagName, mas esses serão criados um objeto TDOMNodeList que deverá ser eventualmente liberado. Isso difere
das outras implementações DOM como MSXML, porque a implementação feita pela FCL é baseada em objeto, não baseada na interface (interface-based).
Os seguintes exemplos demonstram como mostrar os nomes dos nodes para um TMemo localizado em um formulário.
A seguir o arquivo XML chamado 'C:\Programas\teste.xml':
<?xml version="1.0"?>
<images directory="mydir">
<imageNode URL="graphic.jpg" title="">
<Peca DestinoX="0" DestinoY="0">Pecacastelo.jpg1.swf</Peca>
<Peca DestinoX="0" DestinoY="86">Pecacastelo.jpg2.swf</Peca>
</imageNode>
</images>
E aqui o código Pascal para executar a tarefa:
var
Documento: TXMLDocument;
Child: TDOMNode;
j: Integer;
begin
ReadXMLFile(Documento, 'C:\Programas\teste.xml');
Memo.Lines.Clear;
// usando as propriedades FirstChild e NextSibling
Child := Documento.DocumentElement.FirstChild;
while Assigned(Child) do
begin
Memo.Lines.Add(Child.NodeName + ' ' + Child.Attributes.Item[0].NodeValue);
// usando método ChildNodes
with Child.ChildNodes do
try
for j := 0 to (Count - 1) do
Memo.Lines.Add(Item[j].NodeName + ' ' + Item[j].FirstChild.NodeValue);
finally
Free;
end;
Child := Child.NextSibling;
end;
Documento.Free;
end;
Isso mostrará:
imageNode graphic.jpg Peca Pecacastelo.jpg1.swf Peca Pecacastelo.jpg1.swf
Povoando um TreeView com XML
Um uso comum de arquivos XML é analisá-los e mostrar seu conteúdo em uma árvore como formato. Você pode encontrar o componente TTreeView na aba/guia "Common
Controls" do Lazarus.
A função a seguir pegará um documento XML, previamente carregado de um arquivo ou genrado em código, e povoará um TreeView com seu conteúdo. O caption de
cada nó consistirá no conteúdo do primeiro atributo de cada nó.
procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
var
iNode: TDOMNode;
procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode);
var
cNode: TDOMNode;
begin
if Node = nil then Exit; // Pára, se atingir a folha
// Adiciona um nó para a árvore
TreeNode := tree.Items.AddChild(TreeNode, Node.Attributes[0].NodeValue);
// Vai para o primeiro nó filho
cNode := Node.FirstChild;
// Processa todos os nós filhos
while cNode <> nil do
begin
ProcessNode(cNode, TreeNode);
cNode := cNode.NextSibling;
end;
end;
begin
iNode := XMLDoc.DocumentElement.FirstChild;
while iNode <> nil do
begin
ProcessNode(iNode, nil); // Recursivo
iNode := iNode.NextSibling;
end;
end;
Modificando um documento XML
A primeira coisa a ser lembrada é que TDOMDocumento é o "handle" para o DOM. Você pode pegar uma instância dessa classe criando uma ou carregando um
documento XML.
Nós, por outro lado, não podem ser criados como um objeto normal. Você *deve* usar os métodos fornecidos por TDOMDocumento para criá-los, e posteriormente
usar outros métodos para colocá-los no lugar correto na árvore. Isso ocorre porque os nós devem ser "pertencentes" a um documento específico no DOM.
A seguir alguns métodos comuns de TDOMDocument:
function CreateElement(const tagName: DOMString): TDOMElement; virtual;
function CreateTextNode(const data: DOMString): TDOMText;
function CreateCDATASection(const data: DOMString): TDOMCDATASection;
virtual;
function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
E aqui um método de exemplo que localizará o item selelcionado em um TTreeView e inseri-rá um nó filho para o documento XML que ele representa. O TreeView
deve ser previamente preenchido com o conteúdo de um arquivo XML usando a função XML2Tree.
procedure TForm1.actAddChildNode(Sender: TObject);
var
Posicao: Integer;
NovoNo: TDomNode;
begin
{*******************************************************************
* Detecta o elemento selecionado
*******************************************************************}
if TreeView1.Selected = nil then Exit;
if TreeView1.Selected.Level = 0 then
begin
Posicao := TreeView1.Selected.Index;
NovoNo := XMLDoc.CreateElement('item');
TDOMElement(NovoNo).SetAttribute('nome', 'Item');
TDOMElement(NovoNo).SetAttribute('arquivo', 'Arquivo');
with XMLDoc.DocumentElement.ChildNodes do
begin
Item[Posicao].AppendChild(NovoNo);
Free;
end;
{*******************************************************************
* Atualiza o TreeView
*******************************************************************}
TreeView1.Items.Clear;
XML2Tree(TreeView1, XMLDoc);
end
else if TreeView1.Selected.Level >= 1 then
begin
{*******************************************************************
* Essa função funciona somente no primeiro nível da árvore,
* mas pode facilmente ser modificada para funcionar em quaisquer outros níveis
*******************************************************************}
end;
end;
Criar um TXMLDocument de um string
Dado um arquivo XML em MyXmlString, o seguinte código criará esse DOM:
Var
S : TStringStream;
XML : TXMLDocument;
begin
S:= TStringStream.Create(MyXMLString);
Try
S.Position:=0;
XML:=Nil;
ReadXMLFile(XML,S); // Completa o documento XML
// Alternativamente:
ReadXMLFragment(AParentNode,S); // Lê somente um fragmento XML.
Finally
S.Free;
end;
end;
Validando um documento
Desde Março de 2007, DTD validation facility foi adicionado para o analisador XML da FCL. A validação é a verificação da estrutura lógica do documento
conforme as regras pré-definidas, chamadas Documento Type Definition (DTD).
Aqui está um exemplo de um documento XML com um DTD:
<?xml version='1.0'?>
<!DOCTYPE root [
<!ELEMENT root (child)+ >
<!ELEMENT child (#PCDATA)>
]>
<root>
<child>This is a first child.</child>
<child>And this is the second one.</child>
</root>
Esse DTD especifica que o elemento 'root' (raiz) deve ter um ou mais elementos 'child' (filho), e que os elementos 'child' pode ter somente dados de
caractere dentro. Se a análise deteca quaisquer violação dessas regras, ela reportará essas violações.
Carregar o documento dessa forma é um pouco mais complicado. Assumiremos que temos dados XML em um objeto TStream:
procedure TMyObject.DOMFromStream(AStream: TStream);
var
Parser: TDOMParser;
Src: TXMLInputSource;
TheDoc: TXMLDocument;
begin
// cria um objeto analisador
Parser := TDOMParser.Create;
// e a fonte de entrada
Src := TXMLInputSource.Create(AStream);
// nós queremos a validação
Parser.Options.Validate := True;
// associa um manipulador de erro que receberá as notificações
Parser.OnError := @ErrorHandler;
// agora faz o trabalho
Parser.Parse(Src, TheDoc);
// ...e limpeza total
Src.Free;
Parser.Free;
end;
procedure TMyObject.ErrorHandler(E: EXMLReadError);
begin
if E.Severity = esError then // nós estamos interessados somente em erros de validação
writeln(E.Message);
end;
Gerando um arquivo XML
Abaixo um código completo para escrever em arquivo XML. Você pode ler o tutorial completo no blog da DeveLazarus (veja Links Externos) Por favor, lembre das bibliotecas DOM e XMLWrite na cláusula uses
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
DOM, XMLWrite;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
xdoc: TXMLDocument; // variável para o documento
noraiz, nopai, nofilho: TDOMNode; // variáveis dos nós
begin
//cria um documento
xdoc := TXMLDocument.create;
//cria nó raiz
noraiz := xdoc.CreateElement('cadastro');
Xdoc.Appendchild(noraiz); // salva nó raiz
//cria nó pai
noraiz:= xdoc.DocumentElement;
nopai := xdoc.CreateElement('usuario');
TDOMElement(nopai).SetAttribute('id', '001'); // cria atributo para o nó pai
noraiz.Appendchild(nopai); // salva o nó pai
//cria nó filho
nopai := xdoc.CreateElement('nome'); // cria o nó filho
//TDOMElement(nopai).SetAttribute('sexo', 'M'); // cria atributo
nofilho := xdoc.CreateTextNode('Fernando'); // insere um valor para o nó
nopai.Appendchild(nofilho); // salva nó
noraiz.ChildNodes.Item[0].AppendChild(nopai); // insere o nó filho no nó pai correspondente
//cria nó filho
nopai := xdoc.CreateElement('idade'); // cria nó filho
//TDOMElement(nopai).SetAttribute('ano', '1976'); // cria atributo
nofilho := xdoc.CreateTextNode('32'); // coloca um valor ao nó
nopai.Appendchild(nofilho); // salva o nó
noraiz.ChildNodes.Item[0].AppendChild(nopai); // insere o nó filho no nó pai correspondente
writeXMLFile(xDoc,'teste.xml'); // escreve o XML
Xdoc.free; // libera memória
end;
initialization
{$I unit1.lrs}
end.
Resulta no seguinte arquivo XML:
<?xml version="1.0" ?>
- <cadastro>
- <usuario id="001">
<nome>Fernando</nome>
<idade>32</idade>
</usuario>
</cadastro>
--Fernandosinesio 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com
Links Externos
- W3Schools Tutorial Xml
- Thomas Zastrow article FPC e XML