Python para Desenvolvedores

2ª edição, revisada e ampliada

Capítulo 28: XML


XML (eXtensible Markup Language) é uma especificação, desenvolvida pelo World Wide Web Consortium (W3C), para uma representação de dados em que o metadado é armazenado junto com os dados através de marcadores (tags).

Em termos estruturais, um documento XML representa uma hierarquia formada de elementos, que podem ter ou não atributos ou subelementos.

Árvore de elementos XML

Características principais:

  • É legível por software.
  • Pode ser integrada com outras linguagens.
  • Conteúdo e formato são entidades distintas.
  • Marcadores podem ser criados sem limitação.
  • Permite a criação de arquivos para validação de estrutura.

No exemplo, o elemento “Cachorro” possui três atributos: nome, raça e cor. O elemento Lobo tem dois subelementos (“Cachorro” e “Coiote”) e não possui atributos.

Em XML, o cachorro é representado por:

<Cachorro cor="Branco" nome="Bandit" raca="Labrador" />

E o lobo por:

<Lobo>    </Lobo>

Exemplo de elemento XML

Existem vários módulos disponíveis para Python com suporte ao XML, inclusive na biblioteca que acompanha o interpretador.

Entre as APIs mais usados, destacam-se:

  • DOM.
  • SAX.
  • ElementTree.

DOM

Document Object Model (DOM) é um modelo de objeto para representação de XML, independente de plataforma e linguagem. O DOM foi projetado para permitir navegação não linear e modificações arbitrárias. Por isso, o DOM exige que o documento XML (ou pelo menos parte dele) esteja carregado na memória.

Exemplo:

In [2]:
# importa a implementação minidom
import xml.dom.minidom

# Cria o documento
doc = xml.dom.minidom.Document()

# Para ler um documento que já existe
# doc = xml.dom.minidom.parse('caninos.xml')

# Cria os elementos
root = doc.createElement('Canino')
lobo = doc.createElement('Lobo')
raposa = doc.createElement('Raposa')
coiote = doc.createElement('Coiote')
cachorro = doc.createElement('Cachorro')

# Cria os atributos
cachorro.setAttribute('nome', 'Bandit')
cachorro.setAttribute('raca', 'Labrador')
cachorro.setAttribute('cor', 'Branco')

# Cria a estrutura
doc.appendChild(root)
root.appendChild(lobo)
root.appendChild(raposa)
lobo.appendChild(coiote)
lobo.appendChild(cachorro)

# Para acrescentar texto ao elemento
# tex = doc.createTextNode('Melhor amigo do homem...')
# cachorro.appendChild(tex)

# Mostra o XML formatado
print doc.toprettyxml()
<?xml version="1.0" ?>
<Canino>
	<Lobo>
		<Coiote/>
		<Cachorro cor="Branco" nome="Bandit" raca="Labrador"/>
	</Lobo>
	<Raposa/>
</Canino>

O módulo minidom é uma implementação do DOM mais simples e que requer menos memória.

SAX

Simple API for XML (SAX) é uma API de análise sintática serial para XML. SAX permite apenas a leitura serial do documento XML. SAX consome menos memória que o DOM, porém tem menos recursos.

Exemplo:

In [4]:
import xml.sax


# A classe processa a árvore XML
class Handler(xml.sax.handler.ContentHandler):

    def __init__(self):

        xml.sax.handler.ContentHandler.__init__(self)
        self.prefixo = ''

    # É chamado quando uma novo tag é encontrada
    def startElement(self, tag, attr):

        self.prefixo += '  '
        print self.prefixo + 'Elemento:', tag
        for item in attr.items():
            print self.prefixo + '- %s: %s' % item

    # É chamado quando texto é encontrado
    def characters(self, txt):

        if txt.strip():
            print self.prefixo + 'txt:', txt

    # É chamado quando o fim de uma tag é encontrada
    def endElement(self, name):

        self.prefixo = self.prefixo[:-2]


parser = xml.sax.make_parser()
parser.setContentHandler(Handler())
parser.parse('caninos.xml')
  Elemento: Canino
    Elemento: Lobo
      Elemento: Coiote
      Elemento: Cachorro
      - cor: Branco
      - raca: Labrador
      - nome: Bandit
    Elemento: Raposa

Com o SAX não é necessário trazer o documento inteiro para a memória.

ElementTree

ElementTree é o mais “pythônico” dos três, representando uma estrutura XML como uma árvore de elementos, que são tratados de forma semelhante às listas, e nos quais os atributos são chaves, similar aos dicionários.

Exemplo de geração de XML com ElementTree:

In [5]:
from xml.etree.ElementTree import Element, ElementTree

root = Element('Canino')
lobo = Element('Lobo')
raposa = Element('Raposa')
coiote = Element('Coiote')
cachorro = Element('Cachorro', nome='Bandit',
    raca='Labrador', cor='Branco')

root.append(lobo)
root.append(raposa)
lobo.append(coiote)
lobo.append(cachorro)

ElementTree(root).write('caninos.xml')

Exemplo de leitura do arquivo XML:

In [6]:
from xml.etree.ElementTree import ElementTree

tree = ElementTree(file='caninos.xml')
root = tree.getroot()

# Lista os elementos abaixo do root
print root.getchildren()

# Encontra o lobo
lobo = root.find('Lobo')

# Encontra o cachorro
cachorro = lobo.find('Cachorro')
print cachorro.tag, cachorro.attrib

# Remove a raposa
root.remove(root.find('Raposa'))
print root.getchildren()
[<Element 'Lobo' at 0x2b11c50>, <Element 'Raposa' at 0x2b11ed0>]
Cachorro {'nome': 'Bandit', 'cor': 'Branco', 'raca': 'Labrador'}
[<Element 'Lobo' at 0x2b11c50>]

O XML é muito útil por facilitar a interoperabilidade entre sistemas, mesmo que estes sejam desenvolvidos em tecnologias diferentes.

In [1]:
 
Out[1]: