Introduction au format XML¶
XML est un système d'encodage de données largement répandu qui peut être lu par un humain tout comme par un programme. Il est assez verbeux et certainement pas adapté au stockage de très grandes données, cependant on le rencontre assez souvent pour devoir tôt ou tard s'y attaquer. Voici la bibliothèque xml
de Python qui permet de simplifier le processus.
Le but n'est pas d'expliquer XML ici mais de récupérer dans un fichier XML les données qui nous intéressent. Pour cela on va utiliser le fichier XML des prix des carburants à la pompe (cf https://www.prix-carburants.gouv.fr/rubrique/opendata/ ).
# you don't need to understand this cell, it just downloads and opens a zip file from an URL
import requests
import zipfile
import io
import xmltodict
response = requests.get("https://donnees.roulez-eco.fr/opendata/jour", stream=True)
z = zipfile.ZipFile(io.BytesIO(response.content))
xmlfile = z.read(z.filelist[0].filename)
Regardons à quoi ressemble un fichier XML (seulement le début car il est long) :
xmlfile[:1000]
b'<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>\n<pdv_liste>\n <pdv id="1000001" latitude="4620114" longitude="519791" cp="01000" pop="R">\n <adresse>596 AVENUE DE TREVOUX</adresse>\n <ville>SAINT-DENIS-L\xe8S-BOURG</ville>\n <services>\n <service>Station de gonflage</service>\n <service>Vente de gaz domestique (Butane, Propane)</service>\n <service>DAB (Distributeur automatique de billets)</service>\n </services>\n <prix nom="Gazole" id="1" maj="2022-02-25T10:32:40" valeur="1710"/>\n <prix nom="SP95" id="2" maj="2022-02-25T10:08:42" valeur="1809"/>\n <prix nom="SP98" id="6" maj="2022-02-25T10:08:43" valeur="1842"/>\n <rupture id="3" nom="E85" debut="2017-09-16T09:50:23" fin=""/>\n <rupture id="4" nom="GPLc" debut="2017-09-16T09:50:23" fin=""/>\n <rupture id="5" nom="E10" debut="2018-12-13T09:49:49" fin=""/>\n </pdv>\n <pdv id="1000002" latitude="4621842" longitude="522767" cp="01000" pop="R">\n <adresse>16 Avenue de Marboz</adresse>\n <vill'
Disons que l'on désire récupérer l'adresse postale de toutes les stations qui vendent du sans plomb 95, SP95 ou E10, et le prix.
On voit que l'information est stockée dans un arbre dont la racine est pdv_liste
.
Les informations qui nous intéressent sont dans
- chaque élément
pdv
qui est un point de vente, - les sous-éléments
adresse
,ville
etprix
- les attributs
cp
de l'élémentpdv
etvaleur
deprix
On note qu'il y a plusieurs sous-élements prix
par point de vente et qu'il faut donc choisir le bon.
Notre but est de ranger toutes ces informations dans un tableau ayant pour chaque ligne les champs adresse
, cp
, ville
, prix
(prix étant ici la valeur du prix).
Usage de la bibliothèque xml
¶
import xml.etree.ElementTree as ET
root = ET.fromstring(xmlfile)
Si on veut lire un fichier XML et non une URL, alors il faut faire :
tree = ET.parse('data.xml')
root = tree.getroot()
La racine, root, est le premier élément.
Vérifions que notre racine s'appelle bien pdv_liste et qu'il n'y a pas d'attributs pour cet élément :
print(root.tag, root.attrib)
pdv_liste {}
En plus de récupérer son nom tag
et ses attributs attrib
, pour chaque élément il y a trois cas possibles :
- l'élément a des sous élements
- l'élément n'a pas de sous-élements, c'est une feuille, il a un contenu (un texte, un nombre)
- l'élément a des sous-éléments et aussi du contenu qui peut être avant ou après les sous élements.
Les opérations possibles sont suivant les cas :
- on peut
- itérer sur l'élément
for x in element:
- chercher un sous-élement avec
find
ou des sous-élements avecfindall
- itérer sur l'élément
- on peut récupérer la valeur de l'élement avec
text
. - on peut
- itérer ou chercher un ou des sous-éléments
- récupérer la valeur avant les sous-éléments avec
text
- récupérer la valeur après les sous-éléments avec
tail
for element in root:
print(element.tag)
print(element.attrib)
print(element.find('ville').text)
break # it would be too long
len(root)
pdv {'id': '1000001', 'latitude': '4620114', 'longitude': '519791', 'cp': '01000', 'pop': 'R'} SAINT-DENIS-LèS-BOURG
13325
On peut donc écrire notre programme.
result = []
for element in root:
cp = element.attrib['cp']
adresse = element.find('adresse').text
ville = element.find('ville').text
for p in element.findall('prix'):
if p.attrib['nom'] == 'SP95' or p.attrib['nom'] == 'E10':
prix = int(p.attrib['valeur']) / 1000
result.append([adresse, cp, ville, prix])
result[0]
['596 AVENUE DE TREVOUX', '01000', 'SAINT-DENIS-LèS-BOURG', 1.809]
len(result)
11097
Plus¶
Cette présentation n'est qu'une introduction à XML sous Python. Pour plus d'information comme
- éviter les failles de sécurité en lisant un fichier XML récupéré sur le web,
- écrire un fichier XML,
- utiliser un schéma qui décrit le XML,
- et d'autres points
regarder
{{ PreviousNext("11 datetime.ipynb", "90 Project.ipynb")}}