Para muitos programadores Delphi, salvar as configurações está associado ao uso INI arquivos em seus programas. A utilização desse método, em projetos mais ou menos sérios, deve ser evitada, pois limita a flexibilidade, o que impede maior expansão do programa. Deve-se dizer que essa abordagem é bastante popular devido à sua facilidade de uso e à presença de ferramentas integradas no ambiente de desenvolvimento.
No entanto, estruturado XML arquivos. Sua vantagem é que o número de parâmetros não pode ser fixo. Para entender isso melhor, considere um exemplo específico.
No programa USearch, quando você clica em uma entrada, um menu de contexto é exibido, no qual uma lista de itens é exibida. Esses itens são comandos, que por sua vez são carregados do arquivo de configurações. Caso as configurações tenham sido armazenadas em INI, então o programa pode salvar e carregar um certo número de comandos, por exemplo 10 ou 50. Assim que um valor maior for necessário, você terá que reescrever o código e recompilá-lo de acordo.
Aplicando uma abordagem usando XML arquivos, seremos capazes de carregar todos os parâmetros da seção dinamicamente. Além disso, o arquivo de configuração ficará mais elegante, sem numeração redundante de parâmetros. Mas, meios padrão trabalhar com XML Delphi tem muitas desvantagens, então eu recomendo usar biblioteca padrão MSXML... Normalmente, é incluído por padrão em sistemas operacionais Família Windows.
Conectar MSXML, precisamos gerar um arquivo de interface com uma lista de todas as funções, importando-o do servidor COM. Muitos artigos detalhados foram escritos sobre como importar a interface, mas eu sugiro que você baixe o arquivo MSXML2_TLB.PAS pronto para usar. Após o download do arquivo, coloque-o próximo ao seu projeto ou solte-o na pasta lib do ambiente Delphi. Assim, todos os programas criados poderão utilizar o módulo MSXML, você só precisa adicionar a linha MSXML2_TLB para usar.
Para maior clareza, considere o seguinte exemplo de uso desta biblioteca:
Procedimento LoadData; var XMLDoc: DOMDocument; Raiz: IXMLDOMElement; começar XMLDoc: = CoDOMDocument.Create; XMLDoc.Load ("settins.xml"); Raiz: = XMLDoc.DocumentElement; ShowMessage (Root.SelectSingleNode ("tamanho / largura"). Texto); Raiz: = nulo; XMLDoc: = nulo; fim;
Primeiro, uma instância da classe DOMDocument é criada e, em seguida, o conteúdo do arquivo settings.xml é carregado na memória. Uma vez que, de acordo com o padrão, qualquer XML o arquivo deve conter a marca raiz (em nesse caso config), então precisamos obtê-lo usando a função DocumentElement... Em seguida, o conteúdo é exibido entre as tags.
Aqui, o método SelectSingleNode é aplicado, que leva uma string como parâmetro
Apesar de o tópico de trabalho com XML em Delphi ter sido amplamente discutido na Internet, muitas vezes surgem dúvidas sobre esse tópico em todos os tipos de fóruns.
Eu também escrevi isso, mas gostaria de voltar ao caso real de analisar rapidamente um arquivo XML e extrair dados, o que fiz no trabalho hoje. Não demorei mais de 5 minutos para obter os dados necessários.
Fundo. Hoje eu precisava processar dados sobre programas instalados nos computadores dos usuários (sim, sim, identificamos piratas :)). O departamento técnico me forneceu essas informações obtidas de usuários desavisados em uma rede usando WMI. O programa que eles usaram gera relatórios em Formato XML... Conseqüentemente, eles me trouxeram uma montanha de arquivos XML com uma estrutura bastante complexa, da qual eu só tive que extrair o nome dos produtos de software instalados. Tratamento. Depois de olhar alguns arquivos à mão, percebi que não demoraria muito para envelhecer e decidi escrever um pequeno conversor. Tendo iniciado o Delphi, selecionei o objeto XML DataBinding do repositório e alimentei-o com um dos arquivos. Deixei todas as configurações e parâmetros por padrão e, como resultado, um módulo com grande quantia classes e interfaces para acessar os elementos deste arquivo XML. Não me preocupei em lidar com a estrutura das classes por um longo tempo, imediatamente comecei a escrever um conversor. Em um novo aplicativo de console, escrevi um código bem simples:
programa XML2TXT;
usa
Formulários,
Classes, SysUtils,
SoftwareXML em "SoftwareXML.pas";
procedimento CovertXML2Text;
var
softbase: IXMLSTDSoftwareType;
i: inteiro;
sr: TSearchRec;
CurDir: string;
ExportFile: TStringList;
começar
CurDir: = IncludeTrailingPathDelimiter (ExtractFilePath (Application.ExeName));
se FindFirst (CurDir + "*. xml", faAnyFile, sr) = 0, então
repetir
ExportFile: = TStringList.Create;
softbase: = LoadSTDSoftware (Pchar (CurDir + sr.Name));
para i: = 0 para softbase.InstalledSoftware.source.software.Count - 1 faça
ExportFile.Add (softbase.InstalledSoftware.source.software [i] .DisplayName);
ExportFile.Sort;
ExportFile.SaveToFile (CurDir + softbase.InstalledSoftware.Source.servername + ". Txt");
ExportFile.Free;
até FindNext (sr) 0;
fim;
começar
Application.Initialize;
CovertXML2Text;
fim.
Como resultado, obtive um editor de texto para cada computador da grade, contendo uma lista dos softwares instalados.
Acho que este código exigirá alguma explicação. Por exemplo, por que usei o módulo Formulários em um aplicativo de console e chamei o procedimento Application.Initialize;?
Na verdade, é simples - este é um pequeno hack que permite usar XML Data Binding em um aplicativo de console. Porque ele teimosamente se recusou a inicializar a classe para trabalhar com XML. Ainda não descobri os verdadeiros motivos - o tempo de hoje foi importante, já gastei 4 em 5 minutos lutando contra esse erro. :) Acho que depois vou tratar desse problema e escrever qual é o verdadeiro motivo.
A estranha classe softbase foi criada a partir de um arquivo XML - esse é o nome do elemento raiz, e softbase.InstalledSoftware.source.software [i] .DisplayName é apenas navegar pelos elementos aninhados até o desejado e obter seu valor.
É assim que um dos mais maneiras rápidas trabalhando com XML em Delphi.
O XML é cada vez mais usado para armazenar informações e trocá-las entre aplicativos e sites. Muitos aplicativos usam essa linguagem como linguagem base para armazenar dados, enquanto outros a usam para exportar e importar dados XML. Portanto, é hora de os desenvolvedores começarem a pensar sobre como os dados XML podem ser usados em seus próprios aplicativos.
Neste artigo, veremos o XML Document Object Model (DOM) e a implementação da Microsoft do XML DOM.
O XML DOM é um modelo de objeto que fornece a um desenvolvedor objetos para carregar e processar arquivos XML. O modelo de objeto consiste nos seguintes objetos principais: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap e XMLDOMParseError. Cada um desses objetos (exceto XMLDOMParseError) contém propriedades e métodos que permitem obter informações sobre o objeto, manipular os valores e a estrutura do objeto e navegar na estrutura de um documento XML.
Vamos dar uma olhada nos principais objetos XML DOM e mostrar alguns exemplos de seu uso no Borland Delphi.
Usando XML DOM no Borland Delphi
Para usar o Microsoft XML DOM em aplicativos Delphi, você precisa conectar a biblioteca de tipos apropriada ao projeto. Para isso, executamos o comando Projeto | Import Type Library e na caixa de diálogo Import Type Library, selecione a biblioteca Microsoft XML versão 2.0 (Versão 2.0), que geralmente está localizada no arquivo Windows \ System \ MSXML.DLL
Após clicar no botão Criar Unidade, será criado o módulo de interface MSXML_TLB, que nos permitirá utilizar os objetos XML DOM: DOMDocument, XMLDocument, XMLHTTPRequest e vários outros, implementados na biblioteca MSXML.DLL. A referência ao módulo MSXML_TLB deve estar na lista de Usos.
Dispositivo XML DOM
O Document Object Model representa um documento XML em uma estrutura de árvore de ramos. APIs XML DOM permitem que os aplicativos naveguem na árvore do documento e manipulem suas ramificações. Cada ramo pode ter um tipo específico (DOMNodeType), de acordo com o qual os ramos pai e filho são determinados. A maioria dos documentos XML contém ramificações de elemento de tipo, atributo e texto. Os atributos são um tipo especial de ramificação e não são ramificações secundárias. Para gerenciar atributos, use métodos especiais fornecido por objetos XML DOM.
Além de implementar as interfaces recomendadas do World Wide Web Consortium (W3C), o Microsoft XML DOM contém métodos que oferecem suporte a XSL, padrões XSL, namespaces e tipos de dados. Por exemplo, o método SelectNodes permite usar a sintaxe de padrão XSL para localizar ramificações em um contexto específico, e o método TransformNode oferece suporte ao uso de XSL para realizar transformações.
Documento XML de teste
Como um exemplo de documento XML, vamos pegar um diretório de CD-ROM de música, que tem a seguinte estrutura:
Agora estamos prontos para começar a examinar o modelo de objeto XML DOM, começando com o objeto XMLDOMDocument.
Documento XML - objeto XMLDOMDocument
Trabalhar com um documento XML começa com seu carregamento. Para isso, usamos o método Load, que possui apenas um parâmetro que especifica a URL do documento carregado. Ao carregar arquivos de um disco local, apenas o nome completo do arquivo é especificado (o protocolo file: /// pode ser omitido neste caso). Se o documento XML for armazenado como uma string, use o método LoadXML para carregar o documento.
A propriedade Async é usada para controlar como o documento é carregado (síncrono ou assíncrono). Por padrão, esta propriedade é configurada para True, indicando que o documento é carregado de forma assíncrona e o controle é retornado ao aplicativo antes que o documento seja totalmente carregado. Caso contrário, o documento carrega de forma síncrona e, em seguida, você deve verificar o valor da propriedade ReadyState para saber se o documento foi carregado ou não. Você também pode criar um manipulador para o evento OnReadyStateChange que assumirá o controle quando o valor da propriedade ReadyState for alterado.
O seguinte mostra como carregar um documento XML usando o método Load:
Usa ... MSXML_TLB ... procedure TForm1.Button1Click (Sender: TObject); var XMLDoc: IXMLDOMDocument; começar XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // // Aqui é onde está o código que manipula // o documento XML e suas ramificações // XMLDoc: = Nil; fim;
Depois que o documento é carregado, podemos acessar suas propriedades. Portanto, a propriedade NodeName conterá o valor #document, a propriedade NodeTypeString conterá o valor do documento e a propriedade URL conterá o valor file: /// C: /DATA/DATA.xml.
Manipulação de erros
De particular interesse são as propriedades relacionadas ao processamento de documentos no carregamento. Por exemplo, a propriedade ParseError retorna um objeto XMLDOMParseError contendo informações sobre um erro que ocorreu durante o processamento do documento.
Para escrever um gerenciador de erros, você pode adicionar o seguinte código:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load (‘C: \ DATA \ DATA.xml’); XMLError: = XMLDoc.ParseError; If XMLError.ErrorCode<>0 Então // // Aqui tratamos do erro // Else Memo1.Lines.Add (XMLDoc.XML); ... XMLDoc: = Nil;
Para descobrir quais informações são retornadas em caso de erro, altere a seguinte entrada do diretório:
removendo o elemento de fechamento
Agora vamos escrever um código que retorne os valores de propriedade do objeto XMLDOMParseError:
XMLError: = XMLDoc.ParseError; If XMLError.ErrorCode<>0 Em seguida, com XMLError, Memo1.Lines começa a adicionar (‘Arquivo:’ + URL); Adicionar (‘Código:’ + IntToStr (ErrorCode)); Adicionar (‘Erro:’ + Razão); Adicionar (‘Texto:’ + TextoSrc); Adicionar (‘Linha:’ + IntToStr (Linha)); Adicionar (‘Posição:’ + IntToStr (LinePos)); end Else Memo1.Lines.Add (XMLDoc.XML); Fim;
e execute nosso aplicativo. Como resultado, obtemos as seguintes informações sobre o erro.
Como você pode ver no exemplo acima, as informações retornadas pelo objeto XMLDOMParseError são suficientes para localizar o erro e entender a causa de sua ocorrência.
Agora vamos restaurar o elemento de fechamento
Acessando a árvore do documento
Para acessar a árvore do documento, você pode obter o elemento raiz e, a seguir, iterar sobre suas ramificações filhas ou localizar uma ramificação específica. No primeiro caso, obtemos o elemento raiz por meio da propriedade DocumentElement, que retorna um objeto do tipo XMLDOMNode. Veja como usar a propriedade DocumentElement para obter o conteúdo de cada elemento filho:
Nó Var: IXMLDOMNode; Raiz: IXMLDOMElement; I: Inteiro; ... Root: = XMLDoc.DocumentElement; Para I: = 0 para Root.ChildNodes.Length-1 faça Begin Node: = Root.ChildNodes.Item [I]; Memo1.Lines.Add (Node.Text); Fim;
Para nosso documento XML, obtemos o seguinte texto.
Se estivermos interessados em um branch específico ou um branch abaixo do primeiro branch filho, podemos usar o método NodeFromID ou o método GetElementByTagName do objeto XMLDOMDocument.
O método NodeFromID requer um identificador exclusivo conforme definido no Esquema XML ou Definição de Tipo de Documento (DTD) e retorna uma ramificação com esse identificador.
O método GetElementByTagName requer uma string com um elemento específico (tag) e retorna todas as ramificações com este elemento. Veja como usar este método para encontrar todos os artistas em nosso diretório de CD-ROM:
Nós: IXMLDOMNodeList; Nó: IXMLDOMNode; ... Nós: = XMLDoc.GetElementsByTagName (‘ARTIST’); Para I: = 0 para Nodes.Length-1 faça Begin Node: = Nodes.Item [I]; Memo1.Lines.Add (Node.Text); Fim;
Para o nosso documento XML, obteremos o seguinte texto
Observe que o método SelectNodes do objeto XMLDOMNode fornece uma maneira mais flexível de acessar as ramificações do documento. Mas mais sobre isso abaixo.
Filial do Documento - Objeto XMLDOMNode
O objeto XMLDOMNode representa uma ramificação do documento. Já encontramos este objeto quando obtivemos o elemento raiz do documento:
Raiz: = XMLDoc.DocumentElement;
Para obter informações sobre uma ramificação de um documento XML, você pode usar as propriedades do objeto XMLDOMNode (Tabela 1).
Para acessar os dados armazenados em uma ramificação, é comum usar a propriedade NodeValue (disponível para atributos, ramificações de texto, comentários, instruções de processamento e seções CDATA) ou a propriedade Text, que retorna o conteúdo textual da ramificação, ou a propriedade NodeTypedValue. O último, no entanto, só pode ser usado para ramificações com itens digitados.
Navegando na árvore do documento
O objeto XMLDOMNode fornece muitas maneiras de navegar na árvore do documento. Por exemplo, para acessar o branch pai, use a propriedade ParentNode (tipo XMLDOMNode), acesse os branches filho através das propriedades ChildNodes (tipo XMLDOMNodeList), FirstChild e LastChild (tipo XMLDOMNode), etc. A propriedade OwnerDocument retorna um objeto XMLDOMDocument que identifica o próprio documento XML. As propriedades listadas acima facilitam a navegação na árvore do documento.
Agora vamos percorrer todas as ramificações do documento XML:
Raiz: = XMLDoc.DocumentElement; Para I: = 0 para Root.ChildNodes.Length-1 faça Begin Node: = Root.ChildNodes.Item [I]; If Node.HasChildNodes Then GetChilds (Node, 0); Fim;
Conforme observado acima, o SelectNodes do objeto XMLDOMNode fornece uma maneira mais flexível de acessar as ramificações do documento. Além disso, existe um método SelectSingleNode que retorna apenas a primeira ramificação do documento. Ambos os métodos permitem definir modelos XSL para pesquisas de ramificação.
Vejamos o processo de uso do método SelectNodes para buscar todas as ramificações que possuem uma ramificação de CD e uma sub-ramificação PRICE:
Raiz: = XMLDoc.DocumentElement; Nós: = Root.SelectNodes (‘CD / PRICE’);
Todos os sub-ramos PRICE do ramo CD serão colocados na coleção Nodes. Voltaremos a discutir os modelos XSL um pouco mais tarde.
Manipulando ramos filhos
Para manipular ramos filhos, podemos usar os métodos do objeto XMLDOMNode (Tabela 2).
Para excluir completamente o registro sobre o primeiro disco, você precisa executar o seguinte código:
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // Obtenha o elemento raiz Root: = XMLDoc.DocumentElement; Nó: = Raiz; // Remova o primeiro branch filho Node.RemoveChild (Node.FirstChild);
Observe que, neste exemplo, estamos excluindo o primeiro branch filho. Como remover o primeiro elemento do primeiro branch filho é mostrado abaixo:
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // Obtenha o elemento raiz Root: = XMLDoc.DocumentElement; // e o primeiro branch filho Node: = Root.FirstChild; // Remova o primeiro branch filho Node.RemoveChild (Node.FirstChild);
No exemplo acima, não excluímos o primeiro branch
Agora vamos adicionar um novo branch. Abaixo está o código que mostra como adicionar uma nova entrada de CD-ROM de música:
Var NewNode: IXMLDOMNode; Filho: IXMLDOMNode; ... // Crie um novo ramo -
O código acima mostra a seguinte sequência de etapas para adicionar um novo branch:
- Criação de um novo branch usando o método CreateNode:
- criar um elemento usando o método CreateNode;
- adicionar um elemento a uma ramificação usando o método AppendChild;
- definir o valor de um elemento por meio da propriedade Text;
- … Repita para todos os elementos.
- Adicionando uma nova ramificação ao documento usando o método AppendChild.
Lembre-se de que o método AppendChild adiciona um galho ao final da árvore. Para adicionar um ramo a um local específico na árvore, você precisa usar o método InsertBefore.
Conjunto de filiais - objeto XMLDOMNodeList
O objeto XMLNodeList contém uma lista de ramificações, que pode ser construída usando os métodos SelectNodes ou GetElementsByTagName, e também obtida da propriedade ChildNodes.
Já discutimos o uso deste objeto no exemplo fornecido na seção "Navegando na árvore do documento". Aqui iremos fornecer alguns comentários teóricos.
O número de ramos na lista pode ser obtido como o valor da propriedade Comprimento. As ramificações são indexadas de 0 a Comprimento-1 e cada ramificação individual é acessível por meio do item indexado correspondente na matriz Item.
A navegação pela lista de ramificações também pode ser feita usando o método NextNode, que retorna a próxima ramificação da lista ou Nil se a ramificação atual for a última. Para retornar ao topo da lista, chame o método Reset.
Crie e salve documentos
Portanto, cobrimos como você pode adicionar ramificações e elementos a documentos XML existentes. Agora vamos criar um documento XML dinamicamente. Em primeiro lugar, lembre-se de que um documento pode ser carregado não apenas de uma URL, mas também de uma string regular. Veja como criar um elemento raiz, que pode então ser usado para construir dinamicamente o resto dos elementos (que já abordamos na seção Manipulando ramos filho):
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; S: WideString; ... S: = ‘
Após construir o documento XML, salve-o em um arquivo usando o método Save. Por exemplo:
XMLDoc.Save ('C: \ DATA \ NEWCD.XML');
Além de salvar em um arquivo, o método Save permite salvar um documento XML em um novo objeto XMLDOMDocument. Nesse caso, o documento é totalmente processado e, como resultado, sua estrutura e sintaxe são verificadas. Veja como salvar um documento em outro objeto:
Procedimento TForm1.Button2Click (Sender: TObject); var XMLDoc2: IXMLDOMDocument; começar XMLDoc2: = CoDOMDocument.Create; XMLDoc.Save (XMLDoc2); Memo2.Lines.Add (XMLDoc2.XML); ... XMLDoc2: = Nil; fim;
Em conclusão, o método Save também permite salvar o documento XML em outros objetos COM que suportam as interfaces IStream, IPersistStream ou IPersistStreamInit.
Usando modelos XSL
Ao discutir o método SelectNodes do objeto XMLDOMNode, mencionamos que ele fornece uma maneira mais flexível de acessar as ramificações do documento. A flexibilidade é que você pode especificar um modelo XSL como o critério para selecionar ramos. Esses modelos fornecem um mecanismo poderoso para localizar informações em documentos XML. Por exemplo, para obter uma lista de todos os títulos de CD-ROM de música em nosso diretório, você pode executar a seguinte consulta:
Para saber quais discos de artistas são lançados nos EUA, o pedido é feito da seguinte forma:
Nós: = Root.SelectNodes (‘CD / ARTIST’);
Veja como encontrar a primeira unidade em um diretório:
Nós: = Root.SelectNodes (‘CD / TITLE’);
E por ultimo:
Nós: = Root.SelectNodes (‘CD / TITLE’);
Para encontrar os discos de Bob Dylan, você pode executar a seguinte consulta:
Nós: = Root.SelectNodes (‘CD [$ any $ ARTIST =” Bob Dylan ”] / TITLE’);
e para obter uma lista de discos feitos depois de 1985, executamos a seguinte consulta:
Nós: = Root.SelectNodes (‘CD / TITLE’);
Uma discussão mais detalhada da sintaxe XSL requer uma publicação separada. Para intrigar os leitores e encorajar pesquisas futuras, darei apenas um pequeno exemplo do possível uso de XSL. Digamos que precisamos converter nosso catálogo em uma tabela HTML normal. Usando os métodos tradicionais, devemos iterar sobre todos os ramos da árvore e para cada elemento recebido formar as tags correspondentes
Usando XSL, simplesmente criamos um modelo (ou folha de estilo) que especifica o que transformar e como. Em seguida, sobrepomos esse modelo em nosso catálogo - e pronto: temos o texto de um modelo XSL que transforma o catálogo em uma tabela (Listagem 2).
O código para sobrepor um modelo XSL em nosso diretório se parece com este:
Procedimento TForm1.Button2Click (Sender: TObject); var XSLDoc: IXMLDOMDocument; começar XSLDoc: = CoDOMDocument.Create; XSLDoc.Load (‘C: \ DATA \ DATA.xsl’); Memo2.Text: = XMLDoc.TransformNode (XSLDoc); XSLDoc: = Nil; fim;
Concluindo nossa discussão sobre XSL, deve-se dizer que, no momento, essa linguagem é ativamente usada para a transformação entre vários documentos XML, bem como para a formatação de documentos.
Conclusão
Por razões óbvias, é impossível cobrir todos os objetos Microsoft XML DOM e fornecer exemplos de seu uso em um artigo. Aqui, acabamos de abordar as questões básicas do uso de XML DOM em aplicativos. Mesa 3 mostra todos os objetos implementados no Microsoft XML DOM.
ComputerPress 12 "2000
O XML é cada vez mais usado para armazenar informações e trocá-las entre aplicativos e sites. Muitos aplicativos usam essa linguagem como linguagem base para armazenar dados, enquanto outros a usam para exportar e importar dados XML. Portanto, é hora de os desenvolvedores começarem a pensar sobre como os dados XML podem ser usados em seus próprios aplicativos.
Neste artigo, veremos o XML Document Object Model (DOM) e a implementação da Microsoft do XML DOM.
O XML DOM é um modelo de objeto que fornece a um desenvolvedor objetos para carregar e processar arquivos XML. O modelo de objeto consiste nos seguintes objetos principais: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap e XMLDOMParseError. Cada um desses objetos (exceto XMLDOMParseError) contém propriedades e métodos que permitem obter informações sobre o objeto, manipular os valores e a estrutura do objeto e navegar na estrutura de um documento XML.
Vamos dar uma olhada nos principais objetos XML DOM e mostrar alguns exemplos de seu uso no Borland Delphi.
Usando XML DOM no Borland Delphi
Para usar o Microsoft XML DOM em aplicativos Delphi, você precisa conectar a biblioteca de tipos apropriada ao projeto. Para isso, executamos o comando Projeto | Import Type Library e na caixa de diálogo Import Type Library, selecione a biblioteca Microsoft XML versão 2.0 (Versão 2.0), que geralmente está localizada no arquivo Windows \ System \ MSXML.DLL
Após clicar no botão Criar Unidade, será criado o módulo de interface MSXML_TLB, que nos permitirá utilizar os objetos XML DOM: DOMDocument, XMLDocument, XMLHTTPRequest e vários outros, implementados na biblioteca MSXML.DLL. A referência ao módulo MSXML_TLB deve estar na lista de Usos.
Dispositivo XML DOM
O Document Object Model representa um documento XML em uma estrutura de árvore de ramos. APIs XML DOM permitem que os aplicativos naveguem na árvore do documento e manipulem suas ramificações. Cada ramo pode ter um tipo específico (DOMNodeType), de acordo com o qual os ramos pai e filho são determinados. A maioria dos documentos XML contém ramificações de elemento de tipo, atributo e texto. Os atributos são um tipo especial de ramificação e não são ramificações secundárias. Métodos especiais fornecidos por objetos XML DOM são usados para manipular atributos.
Além de implementar as interfaces recomendadas do World Wide Web Consortium (W3C), o Microsoft XML DOM contém métodos que oferecem suporte a XSL, padrões XSL, namespaces e tipos de dados. Por exemplo, o método SelectNodes permite usar a sintaxe de padrão XSL para localizar ramificações em um contexto específico, e o método TransformNode oferece suporte ao uso de XSL para realizar transformações.
Documento XML de teste
Como um exemplo de documento XML, vamos pegar um diretório de CD-ROM de música, que tem a seguinte estrutura:
Agora estamos prontos para começar a examinar o modelo de objeto XML DOM, começando com o objeto XMLDOMDocument.
Documento XML - objeto XMLDOMDocument
Trabalhar com um documento XML começa com seu carregamento. Para isso, usamos o método Load, que possui apenas um parâmetro que especifica a URL do documento carregado. Ao carregar arquivos de um disco local, apenas o nome completo do arquivo é especificado (o protocolo file: /// pode ser omitido neste caso). Se o documento XML for armazenado como uma string, use o método LoadXML para carregar o documento.
A propriedade Async é usada para controlar como o documento é carregado (síncrono ou assíncrono). Por padrão, esta propriedade é configurada para True, indicando que o documento é carregado de forma assíncrona e o controle é retornado ao aplicativo antes que o documento seja totalmente carregado. Caso contrário, o documento carrega de forma síncrona e, em seguida, você deve verificar o valor da propriedade ReadyState para saber se o documento foi carregado ou não. Você também pode criar um manipulador para o evento OnReadyStateChange que assumirá o controle quando o valor da propriedade ReadyState for alterado.
O seguinte mostra como carregar um documento XML usando o método Load:
Usa ... MSXML_TLB ... procedure TForm1.Button1Click (Sender: TObject); var XMLDoc: IXMLDOMDocument; começar XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // // Aqui é onde está o código que manipula // o documento XML e suas ramificações // XMLDoc: = Nil; fim;
Depois que o documento é carregado, podemos acessar suas propriedades. Portanto, a propriedade NodeName conterá o valor #document, a propriedade NodeTypeString conterá o valor do documento e a propriedade URL conterá o valor file: /// C: /DATA/DATA.xml.
Manipulação de erros
De particular interesse são as propriedades relacionadas ao processamento de documentos no carregamento. Por exemplo, a propriedade ParseError retorna um objeto XMLDOMParseError contendo informações sobre um erro que ocorreu durante o processamento do documento.
Para escrever um gerenciador de erros, você pode adicionar o seguinte código:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load (‘C: \ DATA \ DATA.xml’); XMLError: = XMLDoc.ParseError; If XMLError.ErrorCode<>0 Então // // Aqui tratamos do erro // Else Memo1.Lines.Add (XMLDoc.XML); ... XMLDoc: = Nil;
Para descobrir quais informações são retornadas em caso de erro, altere a seguinte entrada do diretório:
removendo o elemento de fechamento
Agora vamos escrever um código que retorne os valores de propriedade do objeto XMLDOMParseError:
XMLError: = XMLDoc.ParseError; If XMLError.ErrorCode<>0 Em seguida, com XMLError, Memo1.Lines começa a adicionar (‘Arquivo:’ + URL); Adicionar (‘Código:’ + IntToStr (ErrorCode)); Adicionar (‘Erro:’ + Razão); Adicionar (‘Texto:’ + TextoSrc); Adicionar (‘Linha:’ + IntToStr (Linha)); Adicionar (‘Posição:’ + IntToStr (LinePos)); end Else Memo1.Lines.Add (XMLDoc.XML); Fim;
e execute nosso aplicativo. Como resultado, obtemos as seguintes informações sobre o erro.
Como você pode ver no exemplo acima, as informações retornadas pelo objeto XMLDOMParseError são suficientes para localizar o erro e entender a causa de sua ocorrência.
Agora vamos restaurar o elemento de fechamento
Acessando a árvore do documento
Para acessar a árvore do documento, você pode obter o elemento raiz e, a seguir, iterar sobre suas ramificações filhas ou localizar uma ramificação específica. No primeiro caso, obtemos o elemento raiz por meio da propriedade DocumentElement, que retorna um objeto do tipo XMLDOMNode. Veja como usar a propriedade DocumentElement para obter o conteúdo de cada elemento filho:
Nó Var: IXMLDOMNode; Raiz: IXMLDOMElement; I: Inteiro; ... Root: = XMLDoc.DocumentElement; Para I: = 0 para Root.ChildNodes.Length-1 faça Begin Node: = Root.ChildNodes.Item [I]; Memo1.Lines.Add (Node.Text); Fim;
Para nosso documento XML, obtemos o seguinte texto.
Se estivermos interessados em um branch específico ou um branch abaixo do primeiro branch filho, podemos usar o método NodeFromID ou o método GetElementByTagName do objeto XMLDOMDocument.
O método NodeFromID requer um identificador exclusivo conforme definido no Esquema XML ou Definição de Tipo de Documento (DTD) e retorna uma ramificação com esse identificador.
O método GetElementByTagName requer uma string com um elemento específico (tag) e retorna todas as ramificações com este elemento. Veja como usar este método para encontrar todos os artistas em nosso diretório de CD-ROM:
Nós: IXMLDOMNodeList; Nó: IXMLDOMNode; ... Nós: = XMLDoc.GetElementsByTagName (‘ARTIST’); Para I: = 0 para Nodes.Length-1 faça Begin Node: = Nodes.Item [I]; Memo1.Lines.Add (Node.Text); Fim;
Para o nosso documento XML, obteremos o seguinte texto
Observe que o método SelectNodes do objeto XMLDOMNode fornece uma maneira mais flexível de acessar as ramificações do documento. Mas mais sobre isso abaixo.
Filial do Documento - Objeto XMLDOMNode
O objeto XMLDOMNode representa uma ramificação do documento. Já encontramos este objeto quando obtivemos o elemento raiz do documento:
Raiz: = XMLDoc.DocumentElement;
Para obter informações sobre uma ramificação de um documento XML, você pode usar as propriedades do objeto XMLDOMNode (Tabela 1).
Para acessar os dados armazenados em uma ramificação, é comum usar a propriedade NodeValue (disponível para atributos, ramificações de texto, comentários, instruções de processamento e seções CDATA) ou a propriedade Text, que retorna o conteúdo textual da ramificação, ou a propriedade NodeTypedValue. O último, no entanto, só pode ser usado para ramificações com itens digitados.
Navegando na árvore do documento
O objeto XMLDOMNode fornece muitas maneiras de navegar na árvore do documento. Por exemplo, para acessar o branch pai, use a propriedade ParentNode (tipo XMLDOMNode), acesse os branches filho através das propriedades ChildNodes (tipo XMLDOMNodeList), FirstChild e LastChild (tipo XMLDOMNode), etc. A propriedade OwnerDocument retorna um objeto XMLDOMDocument que identifica o próprio documento XML. As propriedades listadas acima facilitam a navegação na árvore do documento.
Agora vamos percorrer todas as ramificações do documento XML:
Raiz: = XMLDoc.DocumentElement; Para I: = 0 para Root.ChildNodes.Length-1 faça Begin Node: = Root.ChildNodes.Item [I]; If Node.HasChildNodes Then GetChilds (Node, 0); Fim;
Conforme observado acima, o SelectNodes do objeto XMLDOMNode fornece uma maneira mais flexível de acessar as ramificações do documento. Além disso, existe um método SelectSingleNode que retorna apenas a primeira ramificação do documento. Ambos os métodos permitem definir modelos XSL para pesquisas de ramificação.
Vejamos o processo de uso do método SelectNodes para buscar todas as ramificações que possuem uma ramificação de CD e uma sub-ramificação PRICE:
Raiz: = XMLDoc.DocumentElement; Nós: = Root.SelectNodes (‘CD / PRICE’);
Todos os sub-ramos PRICE do ramo CD serão colocados na coleção Nodes. Voltaremos a discutir os modelos XSL um pouco mais tarde.
Manipulando ramos filhos
Para manipular ramos filhos, podemos usar os métodos do objeto XMLDOMNode (Tabela 2).
Para excluir completamente o registro sobre o primeiro disco, você precisa executar o seguinte código:
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // Obtenha o elemento raiz Root: = XMLDoc.DocumentElement; Nó: = Raiz; // Remova o primeiro branch filho Node.RemoveChild (Node.FirstChild);
Observe que, neste exemplo, estamos excluindo o primeiro branch filho. Como remover o primeiro elemento do primeiro branch filho é mostrado abaixo:
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; XMLDoc: = CoDOMDocument.Create; XMLDoc.Async: = False; XMLDoc.Load (‘C: \ DATA \ DATA.xml’); // Obtenha o elemento raiz Root: = XMLDoc.DocumentElement; // e o primeiro branch filho Node: = Root.FirstChild; // Remova o primeiro branch filho Node.RemoveChild (Node.FirstChild);
No exemplo acima, não excluímos o primeiro branch
Agora vamos adicionar um novo branch. Abaixo está o código que mostra como adicionar uma nova entrada de CD-ROM de música:
Var NewNode: IXMLDOMNode; Filho: IXMLDOMNode; ... // Crie um novo ramo -
O código acima mostra a seguinte sequência de etapas para adicionar um novo branch:
- Criação de um novo branch usando o método CreateNode:
- criar um elemento usando o método CreateNode;
- adicionar um elemento a uma ramificação usando o método AppendChild;
- definir o valor de um elemento por meio da propriedade Text;
- … Repita para todos os elementos.
- Adicionando uma nova ramificação ao documento usando o método AppendChild.
Lembre-se de que o método AppendChild adiciona um galho ao final da árvore. Para adicionar um ramo a um local específico na árvore, você precisa usar o método InsertBefore.
Conjunto de filiais - objeto XMLDOMNodeList
O objeto XMLNodeList contém uma lista de ramificações, que pode ser construída usando os métodos SelectNodes ou GetElementsByTagName, e também obtida da propriedade ChildNodes.
Já discutimos o uso deste objeto no exemplo fornecido na seção "Navegando na árvore do documento". Aqui iremos fornecer alguns comentários teóricos.
O número de ramos na lista pode ser obtido como o valor da propriedade Comprimento. As ramificações são indexadas de 0 a Comprimento-1 e cada ramificação individual é acessível por meio do item indexado correspondente na matriz Item.
A navegação pela lista de ramificações também pode ser feita usando o método NextNode, que retorna a próxima ramificação da lista ou Nil se a ramificação atual for a última. Para retornar ao topo da lista, chame o método Reset.
Crie e salve documentos
Portanto, cobrimos como você pode adicionar ramificações e elementos a documentos XML existentes. Agora vamos criar um documento XML dinamicamente. Em primeiro lugar, lembre-se de que um documento pode ser carregado não apenas de uma URL, mas também de uma string regular. Veja como criar um elemento raiz, que pode então ser usado para construir dinamicamente o resto dos elementos (que já abordamos na seção Manipulando ramos filho):
Var XMLDoc: IXMLDOMDocument; Raiz: IXMLDOMNode; Nó: IXMLDOMNode; S: WideString; ... S: = ‘
Após construir o documento XML, salve-o em um arquivo usando o método Save. Por exemplo:
XMLDoc.Save ('C: \ DATA \ NEWCD.XML');
Além de salvar em um arquivo, o método Save permite salvar um documento XML em um novo objeto XMLDOMDocument. Nesse caso, o documento é totalmente processado e, como resultado, sua estrutura e sintaxe são verificadas. Veja como salvar um documento em outro objeto:
Procedimento TForm1.Button2Click (Sender: TObject); var XMLDoc2: IXMLDOMDocument; começar XMLDoc2: = CoDOMDocument.Create; XMLDoc.Save (XMLDoc2); Memo2.Lines.Add (XMLDoc2.XML); ... XMLDoc2: = Nil; fim;
Em conclusão, o método Save também permite salvar o documento XML em outros objetos COM que suportam as interfaces IStream, IPersistStream ou IPersistStreamInit.
Usando modelos XSL
Ao discutir o método SelectNodes do objeto XMLDOMNode, mencionamos que ele fornece uma maneira mais flexível de acessar as ramificações do documento. A flexibilidade é que você pode especificar um modelo XSL como o critério para selecionar ramos. Esses modelos fornecem um mecanismo poderoso para localizar informações em documentos XML. Por exemplo, para obter uma lista de todos os títulos de CD-ROM de música em nosso diretório, você pode executar a seguinte consulta:
Para saber quais discos de artistas são lançados nos EUA, o pedido é feito da seguinte forma:
Nós: = Root.SelectNodes (‘CD / ARTIST’);
Veja como encontrar a primeira unidade em um diretório:
Nós: = Root.SelectNodes (‘CD / TITLE’);
E por ultimo:
Nós: = Root.SelectNodes (‘CD / TITLE’);
Para encontrar os discos de Bob Dylan, você pode executar a seguinte consulta:
Nós: = Root.SelectNodes (‘CD [$ any $ ARTIST =” Bob Dylan ”] / TITLE’);
e para obter uma lista de discos feitos depois de 1985, executamos a seguinte consulta:
Nós: = Root.SelectNodes (‘CD / TITLE’);
Uma discussão mais detalhada da sintaxe XSL requer uma publicação separada. Para intrigar os leitores e encorajar pesquisas futuras, darei apenas um pequeno exemplo do possível uso de XSL. Digamos que precisamos converter nosso catálogo em uma tabela HTML normal. Usando os métodos tradicionais, devemos iterar sobre todos os ramos da árvore e para cada elemento recebido formar as tags correspondentes
Usando XSL, simplesmente criamos um modelo (ou folha de estilo) que especifica o que transformar e como. Em seguida, sobrepomos esse modelo em nosso catálogo - e pronto: temos o texto de um modelo XSL que transforma o catálogo em uma tabela (Listagem 2).
O código para sobrepor um modelo XSL em nosso diretório se parece com este:
Procedimento TForm1.Button2Click (Sender: TObject); var XSLDoc: IXMLDOMDocument; começar XSLDoc: = CoDOMDocument.Create; XSLDoc.Load (‘C: \ DATA \ DATA.xsl’); Memo2.Text: = XMLDoc.TransformNode (XSLDoc); XSLDoc: = Nil; fim;
Concluindo nossa discussão sobre XSL, deve-se dizer que, no momento, essa linguagem é ativamente usada para a transformação entre vários documentos XML, bem como para a formatação de documentos.
Conclusão
Por razões óbvias, é impossível cobrir todos os objetos Microsoft XML DOM e fornecer exemplos de seu uso em um artigo. Aqui, acabamos de abordar as questões básicas do uso de XML DOM em aplicativos. Mesa 3 mostra todos os objetos implementados no Microsoft XML DOM.
ComputerPress 12 "2000
Eu dou as boas-vindas a todos! Por vários anos, tenho escrito em Matlab e, então, estava impaciente para escrever um programa em Delphi.
Preciso aprender a trabalhar com documentos xml. Eu trabalho na RAD Stiduo XE3. Existe um componente TXMLDocument, provavelmente conhecido por muitos programadores Delphi. Parece ser capaz de fazer muito. Mas o problema é que não há documentação e descrição claras para isso. A ajuda no RAD Studio é uma besteira, porque não há informações normais ali; apenas espalhado pelas páginas de ajuda escassa em alguns métodos e procedimentos (sem exemplos e descrição normal). Vasculhou toda a Internet. Só encontrei tópicos em fóruns com solução de problemas específicos, onde você tem que adivinhar por mais uma hora o que esta ou aquela linha está fazendo, associada ao acesso ao arquivo xml.
Também preciso de um manual sobre as principais funções, procedimentos e métodos usados ao trabalhar com xml. Livro, manual, descrição. Ou pelo menos "xml em Delphi para manequins". Por exemplo:
Para abrir um arquivo xml, use o método XMLDocument1.LoadFromFile ("filemane.xml"), onde filename é o nome do arquivo.
A variável nodelist do tipo IXMLNode é usada para armazenar a lista de filhos. O método Xmldocument1.DocumentElement (em que XMLDocument1 é o arquivo xml a ser examinado) é usado para definir essa lista.
Para consultar o conteúdo do elemento filho "element1", use o método XMLDocument1.DocumentElement.ChildNodes ["element1"]. Text ....
e, com esse espírito, mais adiante em todos os métodos, procedimentos e tipos de dados aplicados.
Onde posso encontrar manuais / descrições semelhantes? Quem pode ajudar?
Se você precisar de uma tarefa específica, vou descrevê-la.
Existe um documento xml no formato:
Algum texto
Algum erro de texto
Outro errortext
No código do programa, temos:
var
...
pai, filho1: IXMLNode;
começar
XMLDocument1.LoadFromFile ("f: \ filename.x ml");
XMLDocument1.Active: = true;
.
.
fim
O que você precisa aprender a fazer:
(Peço desculpas antecipadamente se nomear incorretamente os componentes do documento xml)
1. Obtenha o nome do elemento raiz (no nosso caso, ltm), bem como uma lista de seus atributos (versão, tipo) e seus valores ("1.0", "configurações").
2. Obtenha o número de elementos que são filhos da raiz. Neste caso, existem 7 deles: templateFiles, dimensões, hotspot, hotspot, data, data, data. Obtenha os nomes dos elementos (tags) (templateFiles, dimensões, etc.). Depois de obter o número de elementos e aprender como extrair seus nomes, irei fazer um loop de 0 a count-1 e farei o que preciso.
3. Obtenha o número e a lista de atributos do elemento necessário. Por exemplo, para o elemento de ponto de acesso. A resposta correta seria 4 atributos. Para o primeiro elemento de ponto de acesso, eles serão name, style, scena, ath. Para o segundo - o mesmo, apenas em vez do atributo ath - o atributo rz.
Observe que há 2 elementos de ponto de acesso no arquivo, com atributos diferentes. Veja como trabalhar com eles (se houver mais de 1 elemento com o mesmo nome)?
Eu quero assim: eu recebo uma lista de crianças por rel. para o raiz (consulte a pág. 2), execute um loop for através deles e encontre os elementos do ponto de acesso nos quais o parâmetro de nome é igual ao necessário (diga "hs015_2" - certamente haverá um desses elementos). É possível resolver esse problema de alguma forma sem um loop? Ou seja, obter o valor do atributo scena para o elemento hotspot com name = "hs015_2"?
4. Faça o acima para nós e elementos que são filhos em relação aos filhos. No meu exemplo, um nó (filho de e pai de e.
Se bem entendi, você precisa de alguma forma transferir o conteúdo do nó para variável como IXMLNode e faça o mesmo que nos itens 1-3. Então?
5. Você precisa aprender como alterar os parâmetros acima (definir os seus próprios).
Parece tão longe. Nesse estágio, as construções sintáticas são as mais importantes para mim.
Quem é o proprietário deste tópico, escreva outras construções sintáticas para resolver os problemas acima (como obter atributos, seu número, número de elementos, seus nomes, etc.). O principal agora é dominar a sintaxe e implementarei meu algoritmo mais tarde. Muito obrigado antecipadamente!
P.S. Eu realmente não gostaria de escrever meu próprio analisador XML do zero apenas porque não há uma descrição normal para os existentes.