Python: Parser et indenter un flux XML

Parser un flux XML afin de le valider, extraire des données et l'afficher à l'écran avec une bonne indentation, tout ceci est possible grâce au module xml.dom.minidom.

Exemple avec Python3 et le flux XML suivant:

>>> flux = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><geonames style="MEDIUM"><totalResultsCount>5</totalResultsCount><geoname><toponymName>Republic of Austria</toponymName><name>Austria</name><lat>47.33333</lat><lng>13.33333</lng><geonameId>2782113</geonameId><countryCode>AT</countryCode><countryName>Austria</countryName><fcl>A</fcl><fcode>PCLI</fcode></geoname><geoname><toponymName>Republic of France</toponymName><name>France</name><lat>46</lat><lng>2</lng><geonameId>3017382</geonameId><countryCode>FR</countryCode><countryName>France</countryName><fcl>A</fcl><fcode>PCLI</fcode></geoname><geoname><toponymName>Federal Republic of Germany</toponymName><name>Germany</name><lat>51.5</lat><lng>10.5</lng><geonameId>2921044</geonameId><countryCode>DE</countryCode><countryName>Germany</countryName><fcl>A</fcl><fcode>PCLI</fcode></geoname><geoname><toponymName>Repubblica Italiana</toponymName><name>Italy</name><lat>42.83333</lat><lng>12.83333</lng><geonameId>3175395</geonameId><countryCode>IT</countryCode><countryName>Italy</countryName><fcl>A</fcl><fcode>PCLI</fcode></geoname><geoname><toponymName>Principality of Liechtenstein</toponymName><name>Liechtenstein</name><lat>47.16667</lat><lng>9.53333</lng><geonameId>3042058</geonameId><countryCode>LI</countryCode><countryName>Liechtenstein</countryName><fcl>A</fcl><fcode>PCLI</fcode></geoname></geonames>'
>>> from xml.dom.minidom import parseString
>>> from pprint import pprint
>>> # La commande suivante permet de créer le parseur et de valider le flux XML par la même occasion
>>> parser = parseString(flux)
>>> # La commande suivante permet d'afficher le flux XML correctement indenté
>>> print(parser.toprettyxml())
<?xml version="1.0" ?>
<geonames style="MEDIUM">
    <totalResultsCount>5</totalResultsCount>
    <geoname>
        <toponymName>Republic of Austria</toponymName>
        <name>Austria</name>
        <lat>47.33333</lat>
        <lng>13.33333</lng>
        <geonameId>2782113</geonameId>
        <countryCode>AT</countryCode>
        <countryName>Austria</countryName>
        <fcl>A</fcl>
        <fcode>PCLI</fcode>
    </geoname>
    <geoname>
        <toponymName>Republic of France</toponymName>
        <name>France</name>
        <lat>46</lat>
        <lng>2</lng>
        <geonameId>3017382</geonameId>
        <countryCode>FR</countryCode>
        <countryName>France</countryName>
        <fcl>A</fcl>
        <fcode>PCLI</fcode>
    </geoname>
    <geoname>
        <toponymName>Federal Republic of Germany</toponymName>
        <name>Germany</name>
        <lat>51.5</lat>
        <lng>10.5</lng>
        <geonameId>2921044</geonameId>
        <countryCode>DE</countryCode>
        <countryName>Germany</countryName>
        <fcl>A</fcl>
        <fcode>PCLI</fcode>
    </geoname>
    <geoname>
        <toponymName>Repubblica Italiana</toponymName>
        <name>Italy</name>
        <lat>42.83333</lat>
        <lng>12.83333</lng>
        <geonameId>3175395</geonameId>
        <countryCode>IT</countryCode>
        <countryName>Italy</countryName>
        <fcl>A</fcl>
        <fcode>PCLI</fcode>
    </geoname>
    <geoname>
        <toponymName>Principality of Liechtenstein</toponymName>
        <name>Liechtenstein</name>
        <lat>47.16667</lat>
        <lng>9.53333</lng>
        <geonameId>3042058</geonameId>
        <countryCode>LI</countryCode>
        <countryName>Liechtenstein</countryName>
        <fcl>A</fcl>
        <fcode>PCLI</fcode>
    </geoname>
</geonames>

>>> # On peut également en profiter pour écrire le contenu dans un fichier et correctement indenté
>>> with open('monFlux.xml', 'w') as f:
    f.write(parser.toprettyxml())

    
1494
>>> # Afficher le nombre total d'éléments (correspond à la valeur de la balise totalResultsCount)
>>> print(parser.getElementsByTagName('totalResultsCount')[0].firstChild.data)
5
>>> # La commande suivante permet d'extraire les données d'un tag précis
>>> # et de les sauvegarder dans un dictionnaire
>>> datas = dict()
>>> geonames = parser.getElementsByTagName('geoname')
>>> for geoname in geonames:
    toponymName = geoname.getElementsByTagName('toponymName')[0].firstChild.data
    name = geoname.getElementsByTagName('name')[0].firstChild.data
    lat = geoname.getElementsByTagName('lat')[0].firstChild.data
    lng = geoname.getElementsByTagName('lng')[0].firstChild.data
    geonameid = geoname.getElementsByTagName('geonameId')[0].firstChild.data
    countrycode = geoname.getElementsByTagName('countryCode')[0].firstChild.data
    countryname = geoname.getElementsByTagName('countryName')[0].firstChild.data
    fcl = geoname.getElementsByTagName('fcl')[0].firstChild.data
    fcode = geoname.getElementsByTagName('fcode')[0].firstChild.data
    datas[geonameid] = {'toponymName': toponymName, 'name': name, 'lat': lat, 'lng': lng, 'countryCode': countrycode, 'countryName': countryname, 'fcl': fcl, 'fcode': fcode}

    
>>> pprint(datas)
{'2782113': {'countryCode': 'AT',
             'countryName': 'Austria',
             'fcl': 'A',
             'fcode': 'PCLI',
             'lat': '47.33333',
             'lng': '13.33333',
             'name': 'Austria',
             'toponymName': 'Republic of Austria'},
 '2921044': {'countryCode': 'DE',
             'countryName': 'Germany',
             'fcl': 'A',
             'fcode': 'PCLI',
             'lat': '51.5',
             'lng': '10.5',
             'name': 'Germany',
             'toponymName': 'Federal Republic of Germany'},
 '3017382': {'countryCode': 'FR',
             'countryName': 'France',
             
'fcl': 'A',
             'fcode': 'PCLI',
             'lat': '46',
             'lng': '2',
             'name': 'France',
             'toponymName': 'Republic of France'},
 '3042058': {'countryCode': 'LI',
             'countryName': 'Liechtenstein',
             'fcl': 'A',
             'fcode': 'PCLI',
             'lat': '47.16667',
             'lng': '9.53333',
             'name': 'Liechtenstein',
             'toponymName': 'Principality of Liechtenstein'},
 '3175395': {'countryCode': 'IT',
             'countryName': 'Italy',
             'fcl': 'A',
             'fcode': 'PCLI',
             'lat': '42.83333',
             'lng': '12.83333',
             'name': 'Italy',
             'toponymName': 'Repubblica Italiana'}}
>>>

C'est assez simple dans l'ensemble.