Essa parte é um pouco mais difícil de entender que as duas primeiras. Em primeiro lugar, um elementos chamado contact é criado. Depois são criados três atributos: name, phone e email. Para cada atributo um valor é adicionado. O método setAtribute substitue um atributo existente com o mesmo nome ou cria um novo. Cada chamada dessa função terminará com um elemento que pode ser adicionado a raiz do documento.
A quarta parte é abrir um arquivo, criar um stream de texto e então chamar o método toString() do documento DOM. O exemplo abaixo mostra a função main() completa (incluindo as duas primeiras partes e a chamada a função da terceira parte).
Nessa seção, o plano é ler o documento que nós criamos em uma aplicação e acessa-lo como um documento DOM. Essa tarefa será divida nas seguintes partes:
A primeira parte é mostrada no código abaixo. Um documento vazio é instanciado e o conteúdo do arquivo é associado a ele (se o arquivo foi aberto corretamente). Depois disso, o arquivo pode ser descartado já que o documento inteiro foi carregado na memória.
O próximo passo é encontrar o elemento raiz, ou o elemento do documento, como o Qt se refere a ele. Depois ele é checado para garantir que é um elemento “adbook” e nenhum outro. O código para isso é mostrado abaixo.
As terceira e quarta parte são combinadas em um loop. Cada elemento é checado, se for um contato, os atributos são analisados, se não forem são ignorados. Observe que o método attribute permite um valor padrão, portante, se o atributo estiver faltando nós obteremos uma string vazia. O código é mostrado a seguir.
Observe que usando XML nos é permitido manipular facilmente a compatibilidade de versões antigas do arquivo, já que tipos de elementos e atributos adicionais são ignorados, tornando fácil armazenar dados adicionais em versões futuras.
Essa seção se parecerá muito com a anterior já que se trata de leitura de dados. A diferença é que dessa vez, um leitor SAX será usado. Isso significa que a origem, isso é, o arquivo, precisa estar aberto durante toda a operação pois não haverá buffering.
O SAX no Qt é mais fácil de implementar usando o QXmlSimpleReader e uma sub-classe personalizada de QXmlDefaultHandler. O manipulador padrão tem métodos que podem ser chamados pelo leitor quando um documento inicia, ou um elemento é aberto ou fechado. Nosso manipulador é mostrado no exemplo abaixo e tem dois propósitos: coletar informações do cliente e saber quando está dentro da tag adbook ou não.
O método startDocument é chamado na primeira vez que o documento é aberto. Ele é usado para inicializar o estado da classe para não estar em uma tag adbook. Para cada tag que é aberta. o método startElement é chamado. Ele garante que se uma tag adbook é encontrada, o estado seja alterado, e se um contato for encontrado enquanto estiver dentro da tag adbook os atributos sejam lidos. Finalmente, o método endElement é chamado toda vez que uma tag de fechamento for encontrada. Se uma tag de fechamento do adbook for encontrada, o estado é atualizado.
Usar o AdBookParser é fácil. O exemplo abaixo mostra o código. Primeiro o arquivo é associado ao parser como origem dos dados, depois o manipulador é associado ao leitor que será usado para traduzir os dados da origem. Isso pode parecer um pouco simples, e talvez seja. No mundo das aplicações reais é recomendado usar um QXmlErrorHandler.
O uso do parser SAX permite também implementar a compatibilidade reversa de forma fácil, já que tags e atributos não identificados serão ignorados. Também permite a tradução parcial de arquivos XML ilegais. Por exemplo, apenas a abertura de cada tag de contato é necessária.
A atualização começará como as alterações da classe Contact. Haverá um construtor para criar um Contato a partir de um QDomElement e um para criar um contato vazio. Haverá um método para criar um QDomElement de um contato dado. O cabeçalho e a implementação são mostradas nos dois exemplos a seguir. A implementação é colocada em um novo arquivo chamado contact.cpp.
Observe que o código de createXMLNode é mais ou menos parecido com o código de leitura com DOM da seção correspondente desse capitulo.
Para que possamos manipular o carregamento e salvamento dos arquivo dois novo métodos serão adicionados a classe frmMain. Eles serão usados para facilitar os argumentos de linha de comando e não terão nada a fazer com a interface com o usuário e como o usuário escolhe salvar ou carregar os arquivos. A implementação também é mais ou menos copiada das seções anteriores referentes a leitura e escrita com DOM. A diferença é que elas manipulam coleções de contatos e a listview e também fornecem um feedback melhor quando algo inesperado ocorre. O código é mostrado a seguir.