Apprendre à charger des objets en Python depuis un fichier XML
Par Marc Autran

Le , par autran, Rédacteur
Dans ce billet, je vous propose un petit composant que j'ai écrit sous la forme d'une classe très courte pour charger un catalogue d'objets depuis un fichier XML.

J'ai pris le parti d'utiliser la bibliothèque standard de manipulation XML lxml pour me faciliter la tâche. Cette librairie s'installe directement avec la commande pip install lxml depuis toute station Unix ou Windows connectée à internet (nano PC de type raspberry compris).
Voici le fichier XML que je vais parser :
Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="UTF-8"?> 
<clients> 
    <client> 
        <nom> 
            Ponsable 
        </nom> 
        <prenom> 
            Thérèse 
        </prenom> 
        <email> 
            "therese.ponsable@dumatos.org" 
        </email> 
        <tel> 
            "01020304" 
        </tel> 
    </client> 
     <client> 
        <nom> 
            Rambo 
        </nom> 
        <prenom> 
            John 
        </prenom> 
        <email> 
            "rambo@biscotos.org" 
        </email> 
        <tel> 
            "12356498" 
        </tel> 
    </client> 
    <client> 
        <nom> 
            Rocky 
        </nom> 
        <prenom> 
            Balboa 
        </prenom> 
        <email> 
            "Rocky@baston.org" 
        </email> 
        <tel> 
            "12356498" 
        </tel> 
    </client> 
    <client> 
        <nom> 
            Starsky 
        </nom> 
        <prenom> 
            David 
        </prenom> 
        <email> 
            "david.starsky@guignols.org" 
        </email> 
        <tel> 
            "12356498" 
        </tel> 
    </client> 
</clients>
On remarque que le catalogue de clients est sous le tag <clients> et que chaque client possède un nom, un prenom, un email et un telephone. J'ai choisi de composer des entités XML à partir d'Element XML, mais j'aurais tout aussi bien pu utiliser des attributs. La discussion autour du choix entre attribut et élément restera en dehors du scope de ce billet.
L'objectif de mon chargeur est de créer une liste d'objets Client depuis cette source XML.
Voici le code source de ma classe Client :
Code python : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
class Client : 
    rang = 0 
    def __init__(self, nom, prenom, email, tel): 
        Client.rang += 1 
        self.ident = Client.rang 
        self.nom = nom 
        self.prenom = prenom 
        self.email = email 
        self.tel = tel 
  
    def afficher(self): 
        print(str(self.ident) + " " + self.nom + " " + self.prenom + " " + self.email + " " + self.tel)
J'ai logiquement ajouté à cet objet une méthode qui lui permet de s'afficher. Je l'ai également équipé d'un attribut static rang initialisé à 0 qui s'incrémente à la construction de chaque nouvelle instance, pour servir d'index dans ma collection.
Voici enfin le code source de mon composant :
Code python : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Carnet : 
    def  __init__(self): 
        self.clients = list() 
  
    def ajouter(self, client): 
        self.clients.append(client) 
  
    def afficher(self): 
        for client in self.clients: 
            client.afficher() 
  
    def charger(self, nomFichier): 
        tree = etree.parse(nomFichier) 
        for client in tree.xpath("/clients/client"): 
            self.ajouter(Client(client.find("nom").text, client.find("prenom").text, client.find("email").text, client.find("tel").text))
Je n'utilise qu'un objet de la bibliothèque lxml : la classe etree qui me permet de parser un fichier XML et de mapper l'ensemble des éléments de mon fichier XML dans une collection Python, comme le font les langages modernes (pour feignants) tels que PowerShell.
Pour le test, il suffit de charger le fichier et de l'afficher de cette façon :
Code python : Sélectionner tout
1
2
3
carnet = Carnet() 
carnet.charger("clients.xml") 
carnet.afficher()
Attention, cette petite classe est un composant de dev à modifier pour les besoins de chacun, mais ne constitue en aucun cas une source utilisable en production. En effet, aucun test de validité des valeurs du fichier XML n'est réalisé au chargement.


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster un commentaire

Avatar de Aurelien.Regat-Barrel Aurelien.Regat-Barrel - Expert éminent https://www.developpez.com
le 04/04/2017 à 10:00
Hello,

C'est l'occasion de montrer ce qui m'a poussé à basculer vers Go au lieu de Python. En effet, ce genre de marshaling est géré automatiquement par Go:

Code go : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Client struct { 
    Name    string `xml:"nom"` 
    Surname string `xml:"prenom"` 
    Email   string `xml:"email"` 
    Phone   string `xml:"tel"` 
} 
type Clients struct { 
    Clients []Client `xml:"client"` 
} 
func ChargerClients(data []byte) (Clients, error) { 
    clients := Clients{} 
    err := xml.Unmarshal(data, &clients) 
    return clients, err 
}

Exemple d'appel :

Code go : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
func main() { 
    data, err := ioutil.ReadFile("clients.xml") 
    if err != nil { 
        log.Fatalln(err) 
    } 
    clients, err := ChargerClients(data) 
    if err != nil { 
        log.Fatalln(err) 
    } 
    fmt.Println(clients) 
}

Ca marche aussi pour du json ou du bson (MongoDB)!
Avatar de autran autran - Rédacteur https://www.developpez.com
le 04/04/2017 à 19:27
Merci Aurélien pour le code source
C'est vrai également pour d'autres langages récents. Un camarade vient de me montrer comment faire quelque chose de similaire en PowerShell pour charger une config depuis excel et paramétrer 30 VLAN sur un stack de switch CISCO en un clin d’œil
Offres d'emploi IT
Ingénieur analyste programmeur (H/F)
Safran - Auvergne - Montluçon (03100)
Architecte systèmes études & scientifiques H/F
Safran - Ile de France - Vélizy-Villacoublay (78140)
Développeur java / jee H/F
Capgemini - Ile de France - Suresnes (92150)

Voir plus d'offres Voir la carte des offres IT
Contacter le responsable de la rubrique Accueil