XML Tutorial/pt
한국어 · Bahasa Indonesia · Deutsch · English · Español · Français · Italiano · Magyar · Português · Русский · 中文(中国) · 日本語
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.swfPovoando 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
- Gerando um arquivo XML (Espanhol)
From the Free Pascal wiki, page "XML Tutorial/pt", as it stood on 2020-03-02 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.
Talk about this page
Nobody has opened a bench for this page yet. Sign in to open one.
