Accéder au contenu principal

Tutoriel XML en Python avec ElementTree : Guide du débutant

Apprenez à analyser, explorer, modifier et remplir des fichiers XML avec le paquetage Python ElementTree, les boucles for et les expressions XPath.
Actualisé 14 nov. 2024  · 19 min de lecture

Exécutez et modifiez le code de ce tutoriel en ligne

Exécuter le code

En tant que data scientist, vous découvrirez que la compréhension du XML est très utile pour le web-scraping et la pratique générale de l'analyse syntaxique d'un document structuré.

Maîtrisez vos compétences en matière de données avec DataCamp

Apprenez les compétences dont vous avez besoin à votre propre rythme, des notions essentielles de non-codage à la science des données et à l'apprentissage automatique.

Qu'est-ce que le XML ?

XML signifie "Extensible Markup Language" (langage de balisage extensible). Il est principalement utilisé dans les pages web, où les données ont une structure spécifique et sont comprises dynamiquement par le cadre XML.

XML crée une structure arborescente qui est facile à interpréter et qui prend en charge une hiérarchie. Chaque fois qu'une page suit le langage XML, elle peut être appelée un document XML.

  • Les documents XML comportent des sections, appelées éléments, définies par une balise de début et une balise de fin. Une balise est une construction de balisage qui commence par < et se termine par >. Les caractères entre la balise de début et la balise de fin, s'il y en a, constituent le contenu de l'élément. Les éléments peuvent contenir des balises, y compris d'autres éléments, appelés "éléments enfants".
  • L'élément le plus grand, de niveau supérieur, est appelé la racine, qui contient tous les autres éléments.
  • Les attributs sont des paires nom-valeur qui existent dans une balise start-tag ou empty-element. Un attribut XML ne peut avoir qu'une seule valeur et chaque attribut ne peut apparaître qu'une seule fois sur chaque élément.

Pour mieux comprendre, jetez un coup d'œil au fichier XML (abrégé) suivant :

<?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>

D'après ce que vous avez lu ci-dessus, vous constatez que

  • est l'élément racine unique : il contient tous les autres éléments, tels que , ou , qui sont les éléments enfants ou les sous-éléments. Comme vous pouvez le constater, ces éléments sont imbriqués les uns dans les autres.

Notez que ces éléments enfants peuvent également agir en tant que parents et contenir leurs propres éléments enfants, qui sont alors appelés "éléments sous-enfants".

  • Vous verrez que, par exemple, l'élément contient quelques "attributs", tels que favorite title, qui donnent encore plus d'informations !

Avec cette brève introduction aux fichiers XML en tête, vous êtes prêt à en apprendre davantage sur ElementTree!

Introduction à ElementTree

La structure arborescente XML rend la navigation, la modification et la suppression relativement simples par programmation. Python dispose d'une bibliothèque intégrée, ElementTree, qui contient des fonctions permettant de lire et de manipuler les fichiers XML (et d'autres fichiers structurés de manière similaire).

Tout d'abord, importez ElementTree. Il est courant d'utiliser l'alias ET:

import xml.etree.ElementTree as ET

Analyse des données XML

Le fichier XML fourni décrit une collection de base de films. Le seul problème, c'est que les données sont désordonnées ! Il y a eu de nombreux conservateurs différents de cette collection et chacun a sa propre façon d'entrer les données dans le fichier. L'objectif principal de ce tutoriel sera de lire et de comprendre le fichier avec Python - puis de résoudre les problèmes.

Vous devez d'abord lire le fichier à l'aide de ElementTree.

tree = ET.parse('movies.xml')
root = tree.getroot()

Maintenant que vous avez initialisé l'arbre, vous devriez regarder le XML et imprimer les valeurs afin de comprendre comment l'arbre est structuré.

Chaque partie d'un arbre (y compris la racine) possède une balise qui décrit l'élément. En outre, comme vous l'avez vu dans l'introduction, les éléments peuvent avoir des attributs, qui sont des descripteurs supplémentaires, utilisés en particulier pour l'utilisation répétée des balises. Les attributs permettent également de valider les valeurs saisies pour cette balise, ce qui contribue à nouveau au format structuré d'un XML.

Vous verrez plus loin dans ce tutoriel que les attributs peuvent être très puissants lorsqu'ils sont inclus dans un XML !

root.tag
'collection'

Au niveau supérieur, vous voyez que ce XML est ancré dans la balise collection.

root.attrib
{}

La racine n'a donc pas d'attributs.

Boucles de forçage

Vous pouvez facilement itérer sur les sous-éléments (communément appelés "enfants") de la racine en utilisant une simple boucle "for".

for child in root:
    print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}

Vous savez maintenant que les enfants de la racine collection sont tous genre. Pour désigner le genre, le XML utilise l'attribut category. Il y a des films d'action, des thrillers et des comédies selon l'élément genre.

En règle générale, il est utile de connaître tous les éléments de l'arbre complet. Une fonction utile pour ce faire est root.iter(). Vous pouvez placer cette fonction dans une boucle "for" et elle parcourra l'ensemble de l'arbre.

[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']

Cela donne une idée générale du nombre d'éléments que vous avez, mais ne montre pas les attributs ou les niveaux de l'arbre.

Il existe un moyen utile de consulter l'ensemble du document. Tout élément dispose d'une méthode .tostring(). Si vous transmettez la racine à la méthode .tostring(), vous pouvez renvoyer le document entier. À l'intérieur de ElementTree (dont on se souvient qu'il est alias ET), .tostring() prend une forme un peu étrange.

Comme ElementTree est une bibliothèque puissante qui peut interpréter bien plus que du XML, vous devez spécifier à la fois l'encodage et le décodage du document que vous affichez en tant que chaîne de caractères. Pour les XML, utilisez 'utf8' - il s'agit du type de format de document typique pour un 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>

Vous pouvez étendre l'utilisation de la fonction iter() pour vous aider à trouver des éléments particuliers qui vous intéressent. root.iter() énumère tous les sous-éléments sous la racine qui correspondent à l'élément spécifié. Ici, vous listerez tous les attributs de l'élément movie dans l'arbre :

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'}

Vous pouvez d'ores et déjà constater que les movies ont été saisis de différentes manières. Ne vous en préoccupez pas pour l'instant, vous aurez l'occasion de corriger l'une des erreurs plus loin dans ce tutoriel.

Expressions XPath

Souvent, les éléments n'ont pas d'attributs, ils n'ont qu'un contenu textuel. En utilisant l'attribut .text, vous pouvez imprimer ce contenu.

Imprimez maintenant toutes les descriptions des films.

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

Imprimer le XML est utile, mais XPath est un langage de requête utilisé pour rechercher rapidement et facilement dans un XML. XPath est l'acronyme de XML Path Language et utilise, comme son nom l'indique, une syntaxe de type "chemin" pour identifier et parcourir les nœuds d'un document XML.

Comprendre XPath est d'une importance cruciale pour l'analyse et le remplissage des XML. ElementTree possède une fonction .findall() qui parcourt les enfants immédiats de l'élément référencé. Vous pouvez utiliser des expressions XPath pour spécifier des recherches plus utiles.

Ici, vous rechercherez dans l'arbre les films qui sont sortis en 1992 :

for movie in root.findall("./genre/decade/movie/[year='1992']"):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}

La fonction .findall() commence toujours à l'élément spécifié. Ce type de fonction est extrêmement puissant pour une "recherche et un remplacement". Vous pouvez même effectuer des recherches sur les attributs !

Maintenant, n'imprimez que les films qui sont disponibles en plusieurs formats (un attribut).

for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
    print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}

Réfléchissez à la raison pour laquelle, dans ce cas, l'instruction print renvoie les valeurs "Oui" de multiple. Réfléchissez à la manière dont la boucle "for" est définie. Pourriez-vous réécrire cette boucle pour imprimer les titres des films à la place ? Essayez-le ci-dessous :

Conseil: utilisez '...' à l'intérieur de XPath pour renvoyer l'élément parent de l'élément actuel.

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'}

Modifier un fichier XML

Auparavant, les titres des films étaient un véritable fouillis. Maintenant, imprimez-les à nouveau :

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'}

Corrigez le "2" dans Retour vers le futur. Il devrait s'agir d'un problème de recherche et de remplacement. Écrivez un code pour trouver le titre "Retour vers le futur" et l'enregistrer en tant que variable :

b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>

Notez que la méthode .find() renvoie un élément de l'arbre. La plupart du temps, il est plus utile de modifier le contenu d'un élément.

Modifiez l'attribut title de la variable de l'élément Retour vers le futur pour qu'il se lise "Retour vers le futur". Ensuite, imprimez les attributs de votre variable pour voir votre changement. Vous pouvez facilement le faire en accédant à l'attribut d'un élément et en lui attribuant une nouvelle valeur :

b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}

Rédigez vos modifications dans le fichier XML afin qu'elles soient fixées de manière permanente dans le document. Imprimez à nouveau les attributs de votre film pour vous assurer que vos modifications ont bien été prises en compte. Pour ce faire, utilisez la méthode .write():

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'}

Fixation des attributs

L'attribut multiple est incorrect à certains endroits. Utilisez ElementTree pour fixer l'identifiant en fonction du nombre de formats du film. Tout d'abord, imprimez l'attribut et le texte de format pour voir quelles parties doivent être corrigées.

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

Il y a du travail à faire sur cette étiquette.

Vous pouvez utiliser des expressions rationnelles pour trouver des virgules, qui vous indiqueront si l'attribut multiple doit être "Oui" ou "Non". L'ajout et la modification d'attributs peuvent être effectués facilement avec la méthode .set().

Remarque: re est l'interpréteur de regex standard pour Python. Si vous souhaitez en savoir plus sur les expressions régulières, consultez ce tutoriel.

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

Éléments mobiles

Certaines données ont été placées dans la mauvaise décennie. Utilisez ce que vous avez appris sur XML et ElementTree pour trouver et corriger les erreurs de données de la décennie.

Il sera utile d'imprimer les balises decade et year tout au long du document.

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 

Les deux années qui se situent dans la mauvaise décennie sont les films des années 2000. Déterminez la nature de ces films à l'aide d'une expression XPath.

for movie in root.findall("./genre/decade/movie/[year='2000']"):
    print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}

Vous devez ajouter une nouvelle étiquette de décennie, les années 2000, au genre Action afin de déplacer les données X-Men. La méthode .SubElement() peut être utilisée pour ajouter cette balise à la fin du 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>

Ajoutez maintenant le film X-Men aux années 2000 et retirez-le des années 1990, en utilisant respectivement .append() et .remove().

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>

Construire des documents XML

Vous avez donc réussi à déplacer un film entier dans une nouvelle décennie. Enregistrez vos modifications dans le fichier 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>

Conclusion

Il y a quelques points essentiels à retenir à propos des XML et de l'utilisation de ElementTree.

Les balises construisent l'arborescence et désignent les valeurs qui doivent y être délimitées. L'utilisation d'une structuration intelligente peut faciliter la lecture et l'écriture dans un fichier XML. Les balises ont toujours besoin de parenthèses ouvrantes et fermantes pour indiquer les relations parents-enfants.

Les attributs décrivent en outre comment valider une balise ou permettent des désignations booléennes. Les attributs prennent généralement des valeurs très spécifiques afin que l'analyseur XML (et l'utilisateur) puisse utiliser les attributs pour vérifier les valeurs des balises.

ElementTree est une bibliothèque Python importante qui vous permet d'analyser et de naviguer dans un document XML. L'utilisation de ElementTree permet de décomposer le document XML en une structure arborescente facile à manipuler. En cas de doute, imprimez-le (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - utilisez cette déclaration d'impression utile pour visualiser l'ensemble du document XML en une seule fois. Il est utile de le vérifier lorsque vous modifiez, ajoutez ou supprimez des éléments d'un fichier XML.

Vous êtes maintenant en mesure de comprendre le XML et de commencer à l'analyser !

Références :

Sujets

En savoir plus sur Python

Certification disponible

cours

Introduction à Python

4 hr
5.7M
Maîtrisez les bases de l'analyse de données avec Python en seulement quatre heures. Ce cours en ligne vous présentera l'interface Python et explorera les packages populaires.
Afficher les détailsRight Arrow
Commencer Le Cours
Voir plusRight Arrow