Neste artigo vou ensinar como trabalhar com arquivos XMLs de uma forma sofisticada e de alto nível. Para melhor compreensão deste recurso recomendo a leitura dos artigos Manipulação de XML com TXMLDocument, Manipulação de XML com TXMLDocument – Parte 2 e Manipulação de XML com TXMLDocument – Parte 3. Também estou considerando que você tem uma noção básica sobre XML e XML Schema, mas caso não, recomendo as seções sobre XML e XML Schema do site w3schools.
Utilizaremos nos exemplos o delphi XE, no entanto o XML Data Bind existe desde o Delphi 6, as versões anteriores eu não conheço, assim não posso afirmar se existe ou não o recurso.
Usaremos para esse exemplo um arquivo XML que representa um pedido:
<?xml version="1.0" encoding="ISO-8859-1"?> <shiporder orderid="889923" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="shiporder.biz"> <orderperson>John Smith</orderperson> <shipto> <name>Ola Nordmann</name> <address>Langgt 23</address> <city>4000 Stavanger</city> <country>Norway</country> </shipto> <item> <title>Empire Burlesque</title> <note>Special Edition</note> <quantity>1</quantity> <price>10.90</price> </item> <item> <title>Hide your heart</title> <quantity>1</quantity> <price>9.90</price> </item> </shiporder>
shiporder | Elemento raiz que representa o pedido, ele possui o atributo orderid que possui o código do pedido |
orderperson | Pessoa que fez o pedido |
shipto |
Dados de entrega
|
item |
Dados do produto no pedido
|
Para definir a estrutura e restrições do XML temos o seguinte XML Schema que é chamado de XSD (XML Schema Definition).
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="stringtype"> <xs:restriction base="xs:string"/> </xs:simpleType> <xs:simpleType name="inttype"> <xs:restriction base="xs:positiveInteger"/> </xs:simpleType> <xs:simpleType name="dectype"> <xs:restriction base="xs:decimal"/> </xs:simpleType> <xs:simpleType name="orderidtype"> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{6}"/> </xs:restriction> </xs:simpleType> <xs:complexType name="shiptotype"> <xs:sequence> <xs:element name="name" type="stringtype"/> <xs:element name="address" type="stringtype"/> <xs:element name="city" type="stringtype"/> <xs:element name="country" type="stringtype"/> </xs:sequence> </xs:complexType> <xs:complexType name="itemtype"> <xs:sequence> <xs:element name="title" type="stringtype"/> <xs:element name="note" type="stringtype" minOccurs="0"/> <xs:element name="quantity" type="inttype"/> <xs:element name="price" type="dectype"/> </xs:sequence> </xs:complexType> <xs:complexType name="shipordertype"> <xs:sequence> <xs:element name="orderperson" type="stringtype"/> <xs:element name="shipto" type="shiptotype"/> <xs:element name="item" maxOccurs="unbounded" type="itemtype"/> </xs:sequence> <xs:attribute name="orderid" type="orderidtype" use="required"/> </xs:complexType> <xs:element name="shiporder" type="shipordertype"/> </xs:schema>
Importaremos o arquivo XSD usando o XMLDataBind do delphi que está em: File / New / Other / Delphi Projects / XML, para isso criemos uma nova aplicação no delphi.
Será apresentado um wizard do XML Data Bind. Informe o caminho do arquivo XSD
Nesse exemplo salvamos o arquivo XSD com a extensão .biz, pois o delphi XE não importa corretamente o arquivo se ele possuir a extensão .xsd
Ao clicar em avançar percebemos que na próxima tela foi gerada uma estrutura baseada no arquivo XSD, essas estruturas são interfaces e classes para facilitar a manipulação do XML. Nessa parte se desejar poderá fazer alterações nessas estruturas e interfaces.
Ao clicar novamente em avançar será mostrado uma outra tela com todo o código fonte que será gerado
Agora basta finalizar e salvar a unit gerada pelo wizard.
No TForm da sua aplicação coloque um TMemo, um open dialog e dois TButtons. No evento onClick de um dos TButtons coloque o seguinte código
procedure TForm1.Button1Click(Sender: TObject); var pedido :IXMLShipordertype; item :IXMLItemtype; begin //Cria uma nova instância da estrutura de classes para criar um novo XML pedido := Newshiporder(); //Informações do pedido pedido.Orderid := '123456'; pedido.Orderperson := 'Livraria X'; //Informações do destinatário do pedido pedido.Shipto.Name := 'Jocimar B. A. Huss '; pedido.Shipto.Address := 'R. Carapicuiba 23'; pedido.Shipto.City := 'Mandaguari PR'; pedido.Shipto.Country := 'Brasil'; //Inclui um novo item ao pedido< item := pedido.Item.Add; item.Title := 'Programacacao em Delphi'; item.Quantity := 4; item.Price := '102,33'; item.Note := 'Nao aborda versoes mais antigas da IDE delphi'; //Inclui um novo item ao pedido item := pedido.Item.Add; item.Title := 'Programacacao em Java - Iniciante'; item.Quantity := 1; item.Price := '140,00'; item.Note := 'Somente o basico do java'; Memo1.Text := pedido.XML; memo1.Lines.SaveToFile(ExtractFilePath(Application.ExeName) + 'shiporder.xml'); end;
No evento onClick do outro TButton coloque o seguinte código
procedure TForm1.Button2Click(Sender: TObject); var pedido :IXMLShipordertype; i :Integer; begin OpenDialog1.InitialDir := ExtractFilePath(Application.ExeName); //Pergunta qual arquivo xml deseja abrir if not OpenDialog1.Execute then exit; //Cria uma nova instância da estrutura de classes para fazermos o bind pedido := Loadshiporder(OpenDialog1.FileName); memo1.Clear; //Informações do pedido memo1.Lines.Add('[Informações do pedido]'); memo1.Lines.Add('Código do pedido: ' + pedido.Orderid) memo1.Lines.Add('Pessoa do Pedido: '+pedido.Orderperson); memo1.Lines.Add(''); memo1.Lines.Add('[Dados do destinatário do pedido]'); //Infomações do destinatário do pedido memo1.Lines.Add('Nome: ' + pedido.Shipto.Name); memo1.Lines.Add('Endereço: ' + pedido.Shipto.Address); memo1.Lines.Add('Cidade: ' + pedido.Shipto.City); memo1.Lines.Add('Pais: ' + pedido.Shipto.Country); memo1.Lines.Add(''); //Inclui um novo item ao pedido memo1.Lines.Add('[Itens do pedido]'); for i := 0 to pedido.Item.Count - 1 do begin memo1.Lines.Add('Titulo: ' + pedido.Item[i].Title); memo1.Lines.Add('Quantidade: ' + IntToStr(pedido.Item[i].Quantity)); memo1.Lines.Add('Preço: ' + pedido.Item[i].Price); memo1.Lines.Add('Observação: ' + pedido.Item[i].Note); memo1.Lines.Add(''); end; end;
Pronto, o exemplo já conseguimos gerar um XML e ler um XML gerado na estrutura definida pelo XSD de exemplo. Bom é isso aí, caso tenham dúvidas postem na seção de comentários.
Caso o XML gerado possuir acentos ou outro caractere especial, acontecerá um erro ao carrega-lo. Não pude resolver esse problema, pois não consegui informar o Encoding do XML.
Como faço para colocar o "encoding" no meu novo documento? Alias, muito bom o artigo ^^
ResponderExcluirComo faço a engenharia reversa? A partir das clases geradas pelo xml dta binding, regerar o xsd? Eu não tenho o xsd que gerou as classes e preciso editar/incluir campos no layout do xml. Obrigado
ResponderExcluirEste comentário foi removido pelo autor.
ExcluirNão conheço conheço recurso para fazer a leitura das classes e gerar o XSD, mas é possível que exista, se eu descobrir alguma coisa, postarei aqui no blog.
ExcluirEste comentário foi removido pelo autor.
ResponderExcluirOlá Alexandre. Newshiporder foi criado quando importamos o xsd. Basicamente essa importação do xsd mapeia classes no delphi para a estrutura do xml de exemplo que usamos. Assim facilitando a geração e alteração se um xml. A importação de xsd jà existe desde a versão 6 do Delphi.
ExcluirObrigado Jocimar, Acabei encontrando as Globais, por algum motivo na primeira tentativa que fiz o delphi não as havia gerado, o que naturalmente gerou erro. Mas depois tentei novamente e deu certo.
ExcluirBom dia. Valeu demais pelo artigo. Ajudou em um projeto que eu não estava sabendo nem errar.
ResponderExcluirEste comentário foi removido pelo autor.
ExcluirEste comentário foi removido pelo autor.
ResponderExcluirBoa Noite Pessoal, Jocimar parabéns pelo Artigo
ResponderExcluir