{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Python para Desenvolvedores](http://ricardoduarte.github.io/python-para-desenvolvedores/#conteudo)\n", "===================================\n", "2ª edi\u00e7\u00e3o, revisada e ampliada\n", "-----------------------------------\n", "\n", "Cap\u00edtulo 28: XML\n", "=============================\n", "_____________________________\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "XML (eXtensible Markup Language) \u00e9 uma especifica\u00e7\u00e3o, desenvolvida pelo [World Wide Web Consortium](http://www.w3.org) (W3C), para uma representa\u00e7\u00e3o de dados em que o metadado \u00e9 armazenado junto com os dados atrav\u00e9s de marcadores (tags).\n", "\n", "Em termos estruturais, um documento XML representa uma hierarquia formada de elementos, que podem ter ou n\u00e3o atributos ou subelementos.\n", "\n", "![\u00c1rvore de elementos XML](files/bpypd_diags28.png)\n", "\n", "Caracter\u00edsticas principais:\n", "\n", "+ \u00c9 leg\u00edvel por software.\n", "+ Pode ser integrada com outras linguagens.\n", "+ Conte\u00fado e formato s\u00e3o entidades distintas.\n", "+ Marcadores podem ser criados sem limita\u00e7\u00e3o.\n", "+ Permite a cria\u00e7\u00e3o de arquivos para valida\u00e7\u00e3o de estrutura.\n", "\n", "No exemplo, o elemento \u201cCachorro\u201d possui tr\u00eas atributos: nome, ra\u00e7a e cor. O elemento Lobo tem dois subelementos (\u201cCachorro\u201d e \u201cCoiote\u201d) e n\u00e3o possui atributos.\n", "\n", "Em XML, o cachorro \u00e9 representado por:\n", "\n", " \n", "\n", "E o lobo por:\n", "\n", " \n", "\n", "![Exemplo de elemento XML](files/bpypd_diags29.png)\n", "\n", "Existem v\u00e1rios m\u00f3dulos dispon\u00edveis para Python com suporte ao XML, inclusive na biblioteca que acompanha o interpretador.\n", "\n", "Entre as APIs mais usados, destacam-se:\n", "\n", "+ DOM.\n", "+ SAX.\n", "+ ElementTree.\n", "\n", "DOM\n", "---\n", "*Document Object Model* (DOM) \u00e9 um modelo de objeto para representa\u00e7\u00e3o de XML, independente de plataforma e linguagem. O DOM foi projetado para permitir navega\u00e7\u00e3o n\u00e3o linear e modifica\u00e7\u00f5es arbitr\u00e1rias. Por isso, o DOM exige que o documento XML (ou pelo menos parte dele) esteja carregado na mem\u00f3ria.\n", "\n", "Exemplo:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# importa a implementa\u00e7\u00e3o minidom\n", "import xml.dom.minidom\n", "\n", "# Cria o documento\n", "doc = xml.dom.minidom.Document()\n", "\n", "# Para ler um documento que j\u00e1 existe\n", "# doc = xml.dom.minidom.parse('caninos.xml')\n", "\n", "# Cria os elementos\n", "root = doc.createElement('Canino')\n", "lobo = doc.createElement('Lobo')\n", "raposa = doc.createElement('Raposa')\n", "coiote = doc.createElement('Coiote')\n", "cachorro = doc.createElement('Cachorro')\n", "\n", "# Cria os atributos\n", "cachorro.setAttribute('nome', 'Bandit')\n", "cachorro.setAttribute('raca', 'Labrador')\n", "cachorro.setAttribute('cor', 'Branco')\n", "\n", "# Cria a estrutura\n", "doc.appendChild(root)\n", "root.appendChild(lobo)\n", "root.appendChild(raposa)\n", "lobo.appendChild(coiote)\n", "lobo.appendChild(cachorro)\n", "\n", "# Para acrescentar texto ao elemento\n", "# tex = doc.createTextNode('Melhor amigo do homem...')\n", "# cachorro.appendChild(tex)\n", "\n", "# Mostra o XML formatado\n", "print doc.toprettyxml()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "\n", "\n", "\t\n", "\t\t\n", "\t\t\n", "\t\n", "\t\n", "\n", "\n" ] } ], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "O m\u00f3dulo *minidom* \u00e9 uma implementa\u00e7\u00e3o do DOM mais simples e que requer menos mem\u00f3ria.\n", "\n", "SAX\n", "---\n", "*Simple API for XML* (SAX) \u00e9 uma API de an\u00e1lise sint\u00e1tica serial para XML. SAX permite apenas a leitura serial do documento XML. SAX consome menos mem\u00f3ria que o DOM, por\u00e9m tem menos recursos.\n", "\n", "Exemplo:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import xml.sax\n", "\n", "\n", "# A classe processa a \u00e1rvore XML\n", "class Handler(xml.sax.handler.ContentHandler):\n", "\n", " def __init__(self):\n", "\n", " xml.sax.handler.ContentHandler.__init__(self)\n", " self.prefixo = ''\n", "\n", " # \u00c9 chamado quando uma novo tag \u00e9 encontrada\n", " def startElement(self, tag, attr):\n", "\n", " self.prefixo += ' '\n", " print self.prefixo + 'Elemento:', tag\n", " for item in attr.items():\n", " print self.prefixo + '- %s: %s' % item\n", "\n", " # \u00c9 chamado quando texto \u00e9 encontrado\n", " def characters(self, txt):\n", "\n", " if txt.strip():\n", " print self.prefixo + 'txt:', txt\n", "\n", " # \u00c9 chamado quando o fim de uma tag \u00e9 encontrada\n", " def endElement(self, name):\n", "\n", " self.prefixo = self.prefixo[:-2]\n", "\n", "\n", "parser = xml.sax.make_parser()\n", "parser.setContentHandler(Handler())\n", "parser.parse('caninos.xml')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ " Elemento: Canino\n", " Elemento: Lobo\n", " Elemento: Coiote\n", " Elemento: Cachorro\n", " - cor: Branco\n", " - raca: Labrador\n", " - nome: Bandit\n", " Elemento: Raposa\n" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Com o SAX n\u00e3o \u00e9 necess\u00e1rio trazer o documento inteiro para a mem\u00f3ria.\n", "\n", "ElementTree\n", "-----------\n", "*ElementTree* \u00e9 o mais \u201cpyth\u00f4nico\u201d dos tr\u00eas, representando uma estrutura XML como uma \u00e1rvore de elementos, que s\u00e3o tratados de forma semelhante \u00e0s listas, e nos quais os atributos s\u00e3o chaves, similar aos dicion\u00e1rios.\n", "\n", "Exemplo de gera\u00e7\u00e3o de XML com *ElementTree*:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from xml.etree.ElementTree import Element, ElementTree\n", "\n", "root = Element('Canino')\n", "lobo = Element('Lobo')\n", "raposa = Element('Raposa')\n", "coiote = Element('Coiote')\n", "cachorro = Element('Cachorro', nome='Bandit',\n", " raca='Labrador', cor='Branco')\n", "\n", "root.append(lobo)\n", "root.append(raposa)\n", "lobo.append(coiote)\n", "lobo.append(cachorro)\n", "\n", "ElementTree(root).write('caninos.xml')" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exemplo de leitura do arquivo XML:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from xml.etree.ElementTree import ElementTree\n", "\n", "tree = ElementTree(file='caninos.xml')\n", "root = tree.getroot()\n", "\n", "# Lista os elementos abaixo do root\n", "print root.getchildren()\n", "\n", "# Encontra o lobo\n", "lobo = root.find('Lobo')\n", "\n", "# Encontra o cachorro\n", "cachorro = lobo.find('Cachorro')\n", "print cachorro.tag, cachorro.attrib\n", "\n", "# Remove a raposa\n", "root.remove(root.find('Raposa'))\n", "print root.getchildren()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[, ]\n", "Cachorro {'nome': 'Bandit', 'cor': 'Branco', 'raca': 'Labrador'}\n", "[]\n" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "O XML \u00e9 muito \u00fatil por facilitar a interoperabilidade entre sistemas, mesmo que estes sejam desenvolvidos em tecnologias diferentes." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "" ], "output_type": "pyout", "prompt_number": 1, "text": [ "" ] } ], "prompt_number": 1 } ], "metadata": {} } ] }