[PYTHON] Fonction récursive qui affiche l'arborescence XML [Note]

Que veux-tu faire

J'ai fait des astuces en écrivant la suite de cet article. Je veux faire un mémorandum sur la façon d'exprimer la structure hiérarchique en python lors de la compréhension de la structure arborescente de XML.

environnement

Contexte

    1. La structure XML obtenue à partir de OpenWeatherMap a un concept maximum de 4e étage, et je voudrais clarifier les instructions pour ElementTree lors de l'extraction des données de température / humidité.
  1. Je veux savoir comment afficher XML dans une arborescence pour cela.
    1. Il semble que cela fonctionnait bien si j'appliquais la récurrence, alors j'ai rédigé une note.

Le code que j'ai écrit au début

#Importer la bibliothèque
import urllib.request
import urllib.parse
import xml.etree.ElementTree as et
import xml.dom.minidom as md
url='http://api.openweathermap.org/data/2.5/forecast?' #Paramètre d'URL de base
query = {
        'id'    : '1850144' ,
        'APPID' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', #L'appid que vous avez*1
        'units'  : 'metric',
        'mode'  : 'xml'}#Groupe de valeurs à définir dans la requête
url = url + urllib.parse.urlencode(query) #Demander la génération d'URL
response = urllib.request.urlopen(url) #demande http
root = et.fromstring(response.read()) #Stocker le contenu récupéré dans l'élément XML
for sub1 in root.iter('weatherdata'):
    print("->",sub1.tag, sub1.attrib)
    for sub2 in sub1:
        print("  ->",sub2.tag, sub2.attrib)
        for sub3 in sub2:
            print("    ->",sub3.tag, sub3.attrib)
            for sub4 in sub3:
                print("      ->",sub4.tag, sub4.attrib)

Le résultat du code que j'écrivais en premier

-> weatherdata {}
  -> location {}
    -> name {}
    -> type {}
    -> country {}
    -> timezone {}
    -> location {'altitude': '0', 'latitude': '35.6895', 'longitude': '139.6917', 'geobase': 'geonames', 'geobaseid': '1850144'}
  -> credit {}
  -> meta {}
    -> lastupdate {}
    -> calctime {}
    -> nextupdate {}
  -> sun {'rise': '2017-07-08T19:33:18', 'set': '2017-07-09T09:59:30'}
  -> forecast {}
    -> time {'from': '2017-07-09T12:00:00', 'to': '2017-07-09T15:00:00'}
      -> symbol {'number': '800', 'name': 'clear sky', 'var': '02n'}
      -> precipitation {}
      -> windDirection {'deg': '197.01', 'code': 'SSW', 'name': 'South-southwest'}
      -> windSpeed {'mps': '4.32', 'name': 'Gentle Breeze'}
      -> temperature {'unit': 'celsius', 'value': '23.07', 'min': '23.07', 'max': '23.44'}
      -> pressure {'unit': 'hPa', 'value': '1019.84'}
      -> humidity {'value': '97', 'unit': '%'}
      -> clouds {'value': 'clear sky', 'all': '8', 'unit': '%'}
    -> time {'from': '2017-07-09T15:00:00', 'to': '2017-07-09T18:00:00'}
    (réduction)
    -> time {'from': '2017-07-14T09:00:00', 'to': '2017-07-14T12:00:00'}
      -> symbol {'number': '500', 'name': 'light rain', 'var': '10n'}
      -> precipitation {'unit': '3h', 'value': '0.67', 'type': 'rain'}
      -> windDirection {'deg': '347.003', 'code': 'NNW', 'name': 'North-northeast'}
      -> windSpeed {'mps': '6.57', 'name': 'Moderate breeze'}
      -> temperature {'unit': 'celsius', 'value': '24.1', 'min': '24.1', 'max': '24.1'}
      -> pressure {'unit': 'hPa', 'value': '1012.9'}
      -> humidity {'value': '98', 'unit': '%'}
      -> clouds {'value': 'broken clouds', 'all': '76', 'unit': '%'}

code

Mais quand je pensais que ce n'était pas élégant, j'ai eu l'idée de le rendre récursif et j'ai créé une fonction récursive. J'ai pensé à changer la méthode d'affichage en méthode de répertoire. De cette façon, vous pouvez suivre la profondeur et le chemin complet. De plus, le nom de l'élément racine peut être exprimé de manière abstraite avec root.tag, il devrait donc être utilisable dans divers documents XML.

#Définition des fonctions pour la récurrence
def print_elements( element , depth , fullpath ):
    line = '[' + str(depth) + '] ' + fullpath + '/' + element.tag + str(element.attrib)
    print( line )
    for sub in element:
        print_elements( sub , depth + 1 , fullpath + '/' + element.tag )

#Importer la bibliothèque
import urllib.request
import urllib.parse
import xml.etree.ElementTree as et
import xml.dom.minidom as md
url='http://api.openweathermap.org/data/2.5/forecast?' #Paramètre d'URL de base
query = {
        'id'    : '1850144' ,
        'APPID' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', #L'appid que vous avez*1
        'units'  : 'metric',
        'mode'  : 'xml'}#Groupe de valeurs à définir dans la requête
url = url + urllib.parse.urlencode(query) #Demander la génération d'URL
response = urllib.request.urlopen(url) #demande http
root = et.fromstring(response.read()) #Stocker le contenu récupéré dans l'élément XML
for sub in root.iter(root.tag):
    print_elements( sub , 1 , '')

résultat

[1] /weatherdata{}
[2] /weatherdata/location{}
[3] /weatherdata/location/name{}
[3] /weatherdata/location/type{}
[3] /weatherdata/location/country{}
[3] /weatherdata/location/timezone{}
[3] /weatherdata/location/location{'altitude': '0', 'latitude': '35.6895', 'longitude': '139.6917', 'geobase': 'geonames', 'geobaseid': '1850144'}
[2] /weatherdata/credit{}
[2] /weatherdata/meta{}
[3] /weatherdata/meta/lastupdate{}
[3] /weatherdata/meta/calctime{}
[3] /weatherdata/meta/nextupdate{}
[2] /weatherdata/sun{'rise': '2017-07-08T19:33:19', 'set': '2017-07-09T09:59:29'}
[2] /weatherdata/forecast{}
[3] /weatherdata/forecast/time{'from': '2017-07-09T15:00:00', 'to': '2017-07-09T18:00:00'}
[4] /weatherdata/forecast/time/symbol{'number': '500', 'name': 'light rain', 'var': '10n'}
[4] /weatherdata/forecast/time/precipitation{'unit': '3h', 'value': '0.0075', 'type': 'rain'}
[4] /weatherdata/forecast/time/windDirection{'deg': '204.001', 'code': 'SSW', 'name': 'South-southwest'}
[4] /weatherdata/forecast/time/windSpeed{'mps': '4.31', 'name': 'Gentle Breeze'}
[4] /weatherdata/forecast/time/temperature{'unit': 'celsius', 'value': '23.34', 'min': '22.9', 'max': '23.34'}
[4] /weatherdata/forecast/time/pressure{'unit': 'hPa', 'value': '1019.56'}
[4] /weatherdata/forecast/time/humidity{'value': '100', 'unit': '%'}
[4] /weatherdata/forecast/time/clouds{'value': 'scattered clouds', 'all': '32', 'unit': '%'}
[3] /weatherdata/forecast/time{'from': '2017-07-09T18:00:00', 'to': '2017-07-09T21:00:00'}
(réduction)
[3] /weatherdata/forecast/time{'from': '2017-07-14T12:00:00', 'to': '2017-07-14T15:00:00'}
[4] /weatherdata/forecast/time/symbol{'number': '500', 'name': 'light rain', 'var': '10n'}
[4] /weatherdata/forecast/time/precipitation{'unit': '3h', 'value': '0.27', 'type': 'rain'}
[4] /weatherdata/forecast/time/windDirection{'deg': '320.001', 'code': 'NW', 'name': 'Northwest'}
[4] /weatherdata/forecast/time/windSpeed{'mps': '5.11', 'name': 'Gentle Breeze'}
[4] /weatherdata/forecast/time/temperature{'unit': 'celsius', 'value': '24.35', 'min': '24.35', 'max': '24.35'}
[4] /weatherdata/forecast/time/pressure{'unit': 'hPa', 'value': '1013.6'}
[4] /weatherdata/forecast/time/humidity{'value': '96', 'unit': '%'}
[4] /weatherdata/forecast/time/clouds{'value': 'few clouds', 'all': '20', 'unit': '%'}

Eh bien, il semble que ça s'est bien passé comme ça. Cela fait du bien de pouvoir saisir toute la sensation sans hésitation.

Résumé

La structure en bois était extrêmement profonde. Cette notation peut être bonne pour saisir tout le sentiment. Une expression intermédiaire pour saisir la structure. Utile pour organiser les éléments et les attributs souhaités. Cette fonction récursive peut (devrait) être utilisée dans d'autres documents XML.

Le site que j'ai utilisé comme référence

écran de résultat du notebook jupyter

木構造をディレクトリの様に表示.PNG

Recommended Posts

Fonction récursive qui affiche l'arborescence XML [Note]
Comment résoudre la fonction récursive qui a résolu abc115-D
[Python] Note: Fonction auto-conçue pour trouver la zone de distribution normale
Fonction récursive
Notez que les spécifications de Pandas loc ont changé.
Celui qui affiche la barre de progression en Python
Un programme shell qui affiche une séquence de Fibonacci