Course
Execute e edite o código deste tutorial online
Executar códigoComo cientista de dados, você descobrirá que o conhecimento de XML é poderoso tanto para a extração da Web quanto para a prática geral de análise de um documento estruturado.
- Você aprenderá mais sobre XML e conhecerá o pacote Python
ElementTree
. - Em seguida, você descobrirá como explorar árvores XML para entender melhor os dados com os quais está trabalhando com a ajuda das funções
ElementTree
, loops for e expressões XPath. - Em seguida, você aprenderá como modificar um arquivo XML; e
- Você utilizará expressões xpath para preencher arquivos XML.
O que é XML?
XML significa "Extensible Markup Language" (Linguagem de marcação extensível). É usado principalmente em páginas da Web, onde os dados têm uma estrutura específica e são compreendidos dinamicamente pela estrutura XML.
O XML cria uma estrutura em forma de árvore que é fácil de interpretar e suporta uma hierarquia. Sempre que uma página segue XML, ela pode ser chamada de documento XML.
- Os documentos XML têm seções, chamadas de elementos, definidas por uma tag de início e uma de fim. Uma tag é uma construção de marcação que começa com
<
e termina com>
. Os caracteres entre a tag inicial e a tag final, se houver, são o conteúdo do elemento. Os elementos podem conter marcação, incluindo outros elementos, que são chamados de "elementos filhos". - O maior elemento, de nível superior, é chamado de raiz, que contém todos os outros elementos.
- Os atributos são pares nome-valor que existem em uma tag de início ou de elemento vazio. Um atributo XML só pode ter um único valor e cada atributo pode aparecer no máximo uma vez em cada elemento.
Para entender isso um pouco melhor, dê uma olhada no seguinte arquivo XML (abreviado):
<?xml version="1.0"?>
<collection>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back 2 the Future">
<format multiple="False">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
</genre>
<genre category="Thriller">
<decade years="1970s">
<movie favorite="False" title="ALIEN">
<format multiple="Yes">DVD</format>
<year>1979</year>
<rating>R</rating>
<description>"""""""""</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="True" title="Ferris Bueller's Day Off">
<format multiple="No">DVD</format>
<year>1986</year>
<rating>PG13</rating>
<description>Funny movie about a funny guy</description>
</movie>
<movie favorite="FALSE" title="American Psycho">
<format multiple="No">blue-ray</format>
<year>2000</year>
<rating>Unrated</rating>
<description>psychopathic Bateman</description>
</movie>
</decade>
</genre>
Pelo que você leu acima, você vê que
é o elemento raiz único: ele contém todos os outros elementos, como
, ou
, que são os elementos filhos ou subelementos. Como você pode ver, esses elementos estão aninhados.
Observe que esses elementos filhos também podem atuar como pais e conter seus próprios elementos filhos, que são chamados de "elementos subfilhos".
- Você verá que, por exemplo, o elemento
contém alguns "atributos", como
favorite
title
, que fornecem ainda mais informações!
Com essa breve introdução aos arquivos XML em mente, você está pronto para aprender mais sobre ElementTree
!
Introdução ao ElementTree
A estrutura de árvore XML torna a navegação, a modificação e a remoção relativamente simples em termos de programação. O Python tem uma biblioteca integrada, ElementTree
, que tem funções para ler e manipular XMLs (e outros arquivos estruturados de forma semelhante).
Primeiro, importe ElementTree
. É uma prática comum usar o alias de ET
:
import xml.etree.ElementTree as ET
Analisando dados XML
No arquivo XML fornecido, há uma coleção básica de filmes descrita. O único problema é que os dados estão uma bagunça! Houve muitos curadores diferentes dessa coleção e cada um tem sua própria maneira de inserir dados no arquivo. O principal objetivo deste tutorial será ler e entender o arquivo com Python e, em seguida, corrigir os problemas.
Primeiro, você precisa ler o arquivo com ElementTree
.
tree = ET.parse('movies.xml')
root = tree.getroot()
Agora que você inicializou a árvore, deve examinar o XML e imprimir os valores para entender como a árvore está estruturada.
Cada parte de uma árvore (inclusive a raiz) tem uma tag que descreve o elemento. Além disso, como você viu na introdução, os elementos podem ter atributos, que são descritores adicionais, usados especialmente para o uso repetido de tags. Os atributos também ajudam a validar os valores inseridos para essa tag, contribuindo mais uma vez para o formato estruturado de um XML.
Você verá mais adiante neste tutorial que os atributos podem ser muito poderosos quando incluídos em um XML!
root.tag
'collection'
No nível superior, você vê que esse XML está enraizado na tag collection
.
root.attrib
{}
Portanto, a raiz não tem atributos.
Loops For
Você pode iterar facilmente sobre subelementos (comumente chamados de "filhos") na raiz usando um simples loop "for".
for child in root:
print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}
Agora você sabe que os filhos da raiz collection
são todos genre
. Para designar o gênero, o XML usa o atributo category
. Há filmes de ação, suspense e comédia de acordo com o elemento genre
.
Normalmente, é útil conhecer todos os elementos da árvore inteira. Uma função útil para fazer isso é root.iter()
. Você pode colocar essa função em um loop "for" e ela iterará por toda a árvore.
[elem.tag for elem in root.iter()]
['collection',
'genre',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'genre',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'genre',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'movie',
'format',
'year',
'rating',
'description',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'decade',
'movie',
'format',
'year',
'rating',
'description']
Isso dá uma noção geral de quantos elementos você tem, mas não mostra os atributos ou níveis na árvore.
Há uma maneira útil de ver o documento inteiro. Qualquer elemento tem um método .tostring()
. Se você passar a raiz para o método .tostring()
, poderá retornar o documento inteiro. Em ElementTree
(lembre-se do pseudônimo ET
), .tostring()
assume uma forma um pouco estranha.
Como o ElementTree
é uma biblioteca avançada que pode interpretar mais do que apenas XML, você deve especificar a codificação e a decodificação do documento que está exibindo como string. Para XMLs, use 'utf8'
- esse é o tipo de formato de documento típico para um XML.
print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back 2 the Future">
<format multiple="False">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
</genre>
<genre category="Thriller">
<decade years="1970s">
<movie favorite="False" title="ALIEN">
<format multiple="Yes">DVD</format>
<year>1979</year>
<rating>R</rating>
<description>"""""""""</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="True" title="Ferris Bueller's Day Off">
<format multiple="No">DVD</format>
<year>1986</year>
<rating>PG13</rating>
<description>Funny movie about a funny guy</description>
</movie>
<movie favorite="FALSE" title="American Psycho">
<format multiple="No">blue-ray</format>
<year>2000</year>
<rating>Unrated</rating>
<description>psychopathic Bateman</description>
</movie>
</decade>
</genre>
<genre category="Comedy">
<decade years="1960s">
<movie favorite="False" title="Batman: The Movie">
<format multiple="Yes">DVD,VHS</format>
<year>1966</year>
<rating>PG</rating>
<description>What a joke!</description>
</movie>
</decade>
<decade years="2010s">
<movie favorite="True" title="Easy A">
<format multiple="No">DVD</format>
<year>2010</year>
<rating>PG--13</rating>
<description>Emma Stone = Hester Prynne</description>
</movie>
<movie favorite="True" title="Dinner for SCHMUCKS">
<format multiple="Yes">DVD,digital,Netflix</format>
<year>2011</year>
<rating>Unrated</rating>
<description>Tim (Rudd) is a rising executive
who “succeeds” in finding the perfect guest,
IRS employee Barry (Carell), for his boss’ monthly event,
a so-called “dinner for idiots,” which offers certain
advantages to the exec who shows up with the biggest buffoon.
</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="False" title="Ghostbusters">
<format multiple="No">Online,VHS</format>
<year>1984</year>
<rating>PG</rating>
<description>Who ya gonna call?</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Robin Hood: Prince of Thieves">
<format multiple="No">Blu_Ray</format>
<year>1991</year>
<rating>Unknown</rating>
<description>Robin Hood slaying</description>
</movie>
</decade>
</genre>
</collection>
Você pode expandir o uso da função iter()
para ajudar a encontrar elementos específicos de interesse. root.iter()
listará todos os subelementos sob a raiz que correspondem ao elemento especificado. Aqui, você listará todos os atributos do elemento movie
na árvore:
for movie in root.iter('movie'):
print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
Você já pode ver como o movies
foi inserido de diferentes maneiras. Não se preocupe com isso por enquanto, pois você terá a chance de corrigir um dos erros mais adiante neste tutorial.
Expressões XPath
Muitas vezes, os elementos não têm atributos, eles têm apenas conteúdo de texto. Usando o atributo .text
, você pode imprimir esse conteúdo.
Agora, imprima todas as descrições dos filmes.
for description in root.iter('description'):
print(description.text)
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive
who “succeeds” in finding the perfect guest,
IRS employee Barry (Carell), for his boss’ monthly event,
a so-called “dinner for idiots,” which offers certain
advantages to the exec who shows up with the biggest buffoon.
Who ya gonna call?
Robin Hood slaying
Imprimir o XML é útil, mas o XPath é uma linguagem de consulta usada para pesquisar em um XML de forma rápida e fácil. XPath significa XML Path Language e usa, como o nome sugere, uma sintaxe "semelhante a um caminho" para identificar e navegar pelos nós em um documento XML.
A compreensão do XPath é extremamente importante para a varredura e o preenchimento de XMLs. O site ElementTree
tem uma função .findall()
que percorrerá os filhos imediatos do elemento referenciado. Você pode usar expressões XPath para especificar pesquisas mais úteis.
Aqui, você pesquisará na árvore os filmes que foram lançados em 1992:
for movie in root.findall("./genre/decade/movie/[year='1992']"):
print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
A função .findall()
sempre começa no elemento especificado. Esse tipo de função é extremamente eficiente para "localizar e substituir". Você pode até pesquisar por atributos!
Agora, imprima apenas os filmes que estão disponíveis em vários formatos (um atributo).
for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
Pense em por que, nesse caso, a instrução print retorna os valores "Yes" de multiple
. Pense em como o loop "for" é definido. Você poderia reescrever esse loop para imprimir os títulos dos filmes? Experimente abaixo:
Dica: use '...'
dentro do XPath para retornar o elemento pai do elemento atual.
for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):
print(movie.attrib)
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
Modificação de um XML
Anteriormente, os títulos dos filmes eram uma bagunça absoluta. Agora, imprima-os novamente:
for movie in root.iter('movie'):
print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
Corrigir o '2' em Back 2 the Future. Esse deve ser um problema de localização e substituição. Escreva um código para localizar o título "Back 2 the Future" e salve-o como uma variável:
b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>
Observe que o uso do método .find()
retorna um elemento da árvore. Na maioria das vezes, é mais útil editar o conteúdo de um elemento.
Modifique o atributo title
da variável do elemento Back 2 the Future para ler "Back to the Future". Em seguida, imprima os atributos de sua variável para ver a alteração. Você pode fazer isso facilmente acessando o atributo de um elemento e, em seguida, atribuindo um novo valor a ele:
b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}
Escreva suas alterações de volta no XML para que elas sejam permanentemente fixadas no documento. Imprima os atributos do filme novamente para ter certeza de que as alterações funcionaram. Use o método .write()
para fazer isso:
tree.write("movies.xml")
tree = ET.parse('movies.xml')
root = tree.getroot()
for movie in root.iter('movie'):
print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back to the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
Fixação de atributos
O atributo multiple
está incorreto em alguns lugares. Use ElementTree
para fixar o designador com base em quantos formatos o filme está disponível. Primeiro, imprima o atributo format
e o texto para ver quais partes precisam ser corrigidas.
for form in root.findall("./genre/decade/movie/format"):
print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'False'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'Yes'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'No'} Online,VHS
{'multiple': 'No'} Blu_Ray
Há algum trabalho que precisa ser feito nessa etiqueta.
Você pode usar regex para localizar vírgulas, que dirão se o atributo multiple
deve ser "Yes" ou "No". A adição e a modificação de atributos podem ser feitas facilmente com o método .set()
.
Observação: re
é o interpretador de regex padrão para Python. Se você quiser saber mais sobre expressões regulares, considere este tutorial.
import re
for form in root.findall("./genre/decade/movie/format"):
# Search for the commas in the format text
match = re.search(',',form.text)
if match:
form.set('multiple','Yes')
else:
form.set('multiple','No')
# Write out the tree to the file again
tree.write("movies.xml")
tree = ET.parse('movies.xml')
root = tree.getroot()
for form in root.findall("./genre/decade/movie/format"):
print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'No'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'No'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'Yes'} Online,VHS
{'multiple': 'No'} Blu_Ray
Elementos móveis
Alguns dos dados foram colocados na década errada. Use o que você aprendeu sobre XML e ElementTree
para localizar e corrigir os erros de dados da década.
Será útil imprimir as tags decade
e year
em todo o documento.
for decade in root.findall("./genre/decade"):
print(decade.attrib)
for year in decade.findall("./movie/year"):
print(year.text, '\n')
{'years': '1980s'}
1981
1984
1985
{'years': '1990s'}
2000
1992
1992
{'years': '1970s'}
1979
{'years': '1980s'}
1986
2000
{'years': '1960s'}
1966
{'years': '2010s'}
2010
2011
{'years': '1980s'}
1984
{'years': '1990s'}
1991
Os dois anos que estão na década errada são os filmes dos anos 2000. Descubra quais são esses filmes usando uma expressão XPath.
for movie in root.findall("./genre/decade/movie/[year='2000']"):
print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}
É necessário adicionar uma nova etiqueta de década, os anos 2000, ao gênero Ação para mover os dados dos X-Men. O método .SubElement()
pode ser usado para adicionar essa tag ao final do XML.
action = root.find("./genre[@category='Action']")
new_dec = ET.SubElement(action, 'decade')
new_dec.attrib["years"] = '2000s'
print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back to the Future">
<format multiple="No">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
<decade years="2000s" /></genre>
Agora, acrescente o filme X-Men à década de 2000 e remova-o da década de 1990, usando .append()
e .remove()
, respectivamente.
xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)
print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back to the Future">
<format multiple="No">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
<decade years="2000s"><movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
</decade></genre>
Criar documentos XML
Legal, então você conseguiu basicamente mudar um filme inteiro para uma nova década. Salve suas alterações de volta no XML.
tree.write("movies.xml")
tree = ET.parse('movies.xml')
root = tree.getroot()
print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the
Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back to the Future">
<format multiple="No">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
<decade years="2000s"><movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must
oppose a terrorist organization with similar powers.</description>
</movie>
</decade></genre>
<genre category="Thriller">
<decade years="1970s">
<movie favorite="False" title="ALIEN">
<format multiple="No">DVD</format>
<year>1979</year>
<rating>R</rating>
<description>"""""""""</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="True" title="Ferris Bueller's Day Off">
<format multiple="No">DVD</format>
<year>1986</year>
<rating>PG13</rating>
<description>Funny movie about a funny guy</description>
</movie>
<movie favorite="FALSE" title="American Psycho">
<format multiple="No">blue-ray</format>
<year>2000</year>
<rating>Unrated</rating>
<description>psychopathic Bateman</description>
</movie>
</decade>
</genre>
<genre category="Comedy">
<decade years="1960s">
<movie favorite="False" title="Batman: The Movie">
<format multiple="Yes">DVD,VHS</format>
<year>1966</year>
<rating>PG</rating>
<description>What a joke!</description>
</movie>
</decade>
<decade years="2010s">
<movie favorite="True" title="Easy A">
<format multiple="No">DVD</format>
<year>2010</year>
<rating>PG--13</rating>
<description>Emma Stone = Hester Prynne</description>
</movie>
<movie favorite="True" title="Dinner for SCHMUCKS">
<format multiple="Yes">DVD,digital,Netflix</format>
<year>2011</year>
<rating>Unrated</rating>
<description>Tim (Rudd) is a rising executive
who “succeeds” in finding the perfect guest,
IRS employee Barry (Carell), for his boss’ monthly event,
a so-called “dinner for idiots,” which offers certain
advantages to the exec who shows up with the biggest buffoon.
</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="False" title="Ghostbusters">
<format multiple="Yes">Online,VHS</format>
<year>1984</year>
<rating>PG</rating>
<description>Who ya gonna call?</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="True" title="Robin Hood: Prince of Thieves">
<format multiple="No">Blu_Ray</format>
<year>1991</year>
<rating>Unknown</rating>
<description>Robin Hood slaying</description>
</movie>
</decade>
</genre>
</collection>
Conclusão
Há alguns aspectos importantes a serem lembrados sobre XMLs e o uso do site ElementTree
.
As tags criam a estrutura da árvore e designam quais valores devem ser delineados nela. O uso da estruturação inteligente pode facilitar a leitura e a gravação em um XML. As tags sempre precisam de colchetes de abertura e fechamento para mostrar as relações entre pai e filho.
Os atributos descrevem ainda como validar uma tag ou permitem designações booleanas. Os atributos normalmente assumem valores muito específicos para que o analisador XML (e o usuário) possa usar os atributos para verificar os valores das tags.
ElementTree
é uma importante biblioteca Python que permite analisar e navegar em um documento XML. O uso do site ElementTree
divide o documento XML em uma estrutura de árvore fácil de trabalhar. Em caso de dúvida, imprima-o (print(ET.tostring(root, encoding='utf8').decode('utf8'))
) - use essa declaração de impressão útil para visualizar todo o documento XML de uma só vez. Isso ajuda a verificar ao editar, adicionar ou remover de um XML.
Agora você está preparado para entender o XML e começar a analisá-lo!
Referências:
Saiba mais sobre Python
Course
Intermediate Python
Course
Introduction to Functions in Python
tutorial
Tutorial do Python Excel: O guia definitivo
tutorial
Tutorial do Python pandas: O guia definitivo para iniciantes
tutorial
Tutorial de análise de sentimentos com NLTK para iniciantes
tutorial
21 ferramentas essenciais do Python
tutorial
Perfilamento do Pandas (ydata-profiling) em Python: Um guia para iniciantes
Satyam Tripathi
9 min
tutorial