Manipulando XML com Python

Neste post mostro algumas formas básicas de ler (parse) e de buscar informações de um XML, que pode vir de um arquivo, uma string ou um web-service (que também é uma string, mas tudo bem).  A biblioteca utiliza aqui é a etree.

Antes de começarmos a trabalhar com o XML, vamos fazer o import das bibliotecas que vamos utilizar:

 

Vamos ver 3 formas de converter o XML em um objeto ElementTree. A primeira forma é lendo XML de um arquivo, a segunda é lendo de uma string e a terceira é fazendo uma requisição a um web-service e lendo o resultado.

Para informação, a fonte de dados que utilizo neste exemplo é o catalogo de CDs que o site W3Schools oferece como exemplo de XML.

Lendo um XML de um Arquivo

Difícil, não? Pois é. o objeto armazenado na variável tree possui todas as referências para o arquivo. Se o arquivo estiver com algum problema, a biblioteca vai gerar uma exception.

 

Lendo um XML de uma string

Bom, esta forma de leitura possui menos linhas, mas merece uma explicação melhor. A função fromstring() foi desenhada para ler pedaços de um XML. Ele consegue ler um documento inteiro sem problemas, mas ele devolve o ‘root‘  (raiz) do documento, ou seja, o elemento raiz. Sendo assim, você não consegue padronizar o comportamento na hora de processar o XML. Mais para frente neste post vou apontar onde ocorreria um erro.

Então o que fazemos é converter a string com XML em um objeto root e depois converter este root em um objeto ElementTree, que vai ter o mesmo comportamento do objeto retornado pela função parse (utilizada na leitura do XML a partir de um arquivo).

 

Lendo um XML de um web-service

O código acima segue a mesma lógica da leitura de um XML a partir de uma string, mas achei importante separar as duas coisas para chamar atenção na forma como a requisição foi feita.

Perceba que defini um header especifico, que indica o tipo de resposta desejada. Sem ele, você pode receber a resposta do web-service de uma forma que não está esperando. Lembre-se: quando você especifica um tipo de resposta, você também cria a chance de que algo de errado aconteça como, por exemplo, o web-service só conseguir responder em json.

 

Forma do XML neste exemplo

O nosso XML de exemplo possui esta forma:

  • A raiz (root) do documento, que é a tag CATALOG;
  • Lista de elementos, que são definidos pela tag <CD> …. </CD>
  • Dentro de cada elemento (<CD>), existem outros elementos que caracterizam um CD.
  • Este documento não possui tags com atributos.
    • Um atributo é uma propriedade que fica dentro da tag. Exemplo: <CD produtora=”Março Musical”>

 

Ok. Agora que já sabemos a forma do XML, vamos extrair as informações dele.

 

 

Recuperando elemento raiz (root)

Para recuperar o elemento root do documento, basta utilizar a função abaixo:

Este objeto é do mesmo tipo que é retornado pela função fromstring() e este é o ponto que pode ocorrer um erro. Se você utilizar a função fromstring na hora de ler o XML de uma string, quando você utilizar a função getroot, vai ocorrer o seguinte erro…

 

AttributeError: ‘xml.etree.ElementTree.Element’ object has no attribute ‘getroot’

 

… pois o elemento já é o root.

 

Parece que estou complicando, né? Mas considere a seguinte situação: Você tem uma aplicação que lê um arquivo XML e depois faz uma série de processamentos. Se a sua aplicação passar a ler o XML de uma string e utilizar a função fromstring, no ponto em que o sistema tenta recuperar o root do documento, vai ocorrer um erro.  Então, se você converter o resultado da função fromstring em um ElementTree, o resto da sua aplicação não precisa mudar.

Claro que esta não é a única forma de padronizar o comportamento do sistema, mas achei importante deixar claro que isso pode acontecer.

 

Fazendo uma iteração geral por todos os elementos

No código acima, a função iter vai retornar um objeto iterable, utilizando como filtro o valor da variável filtro.

Para exibir os resultados, utilizo duas propriedades:

  • child.tag: Mostra o texto (string) que está <dentro da tag>;
  • child.text: Mostra o conteúdo da tag;

Esta função vai retornar todos os objetos que são filhos (diretos ou não) do elemento raiz. Sendo assim, o resultado do código acima seria este:

 

Neste caso, todos os elementos do documento foram percorridos, mas não existe muito controle de hierarquia…

 

Listando o titulo dos CDS

No código acima, utilizo a função findall para retornar todos os objetos com a tag CD. Como este XML não utiliza atributos, cada detalhe de cada CD é outro elemento que deve ser procurado.

Sendo assim, no segundo for, utilizado a função findall para buscar todas as tags TITLE. Para cada objeto referente a tag title, utilizo print para exibir o conteúdo dela.

 

O código acima vai mostrar os titulos de todos os cds que existem no catalogo:

 

 

Existem outras formas de encontrar elementos dentro de um documento como, por exemplo, utilizando um padrão xpath, mas preferi manter este post com as informações básicas e simples. Se precisar, faço uma sequência para este post.

 

Espero ter ajudado!

The following two tabs change content below.
Breno RdV
Ex-Psicólogo, com quase uma década de experiência em Recursos Humanos e Gestão de Pessoas, atual desenvolvedor e Analista de Sistemas, trabalhando com PowerBuilder, C#, PowerShell e expandindo horizontes para Python, Xamarin, PHP, Angular e (por que não?) Unity.

Comments

comments

Posted in Dev, Python and tagged , , .