2010-08-26 5 views
0

Je travaille avec XML et Python pour la première fois. Le but ultime est d'envoyer une requête à un service REST, de recevoir une réponse en XML, d'analyser les valeurs et d'envoyer des emails en fonction de ce qui a été retourné. Cependant, le service REST n'est pas encore en place, donc pour l'instant j'expérimente avec un fichier XML enregistré sur mon disque C.Essayer d'analyser un fichier XML avec Python - qu'est-ce que je fais de mal?

J'ai un simple code, et je ne sais pas pourquoi cela ne fonctionne pas.

Ceci est mon fichier xml ("xmltest.xml"):

<Response> 
    <exitCode>1</exitCode> 
    <fileName>C:/Something/</fileName> 
    <errors> 
     <error>Error generating report</error> 
    </errors> 
</Response> 

Ceci est mon code à ce jour:

from xml.dom import minidom 

something = open("C:/XMLTest.xml") 
something = minidom.parse(something) 

nodeList = [] 
for node in something.getElementsByTagName("Response"): 
    nodeList.extend(t.nodeValue for t in node.childNodes) 
print nodeList 

Mais les résultats impriment sont ...

[u'\n\t', None, u'\n\t', None, u'\n\t', None, u'\n'] 

Qu'est-ce que je fais mal?

J'essaie d'obtenir les valeurs de noeud. Y a-t-il une meilleure manière de faire cela? Existe-t-il une méthode intégrée en Python pour convertir un fichier xml en un objet ou un dictionnaire? J'aimerais obtenir toutes les valeurs, de préférence avec les noms ci-joints.

+0

C'est ce que j'attendrais du code que vous avez posté pour imprimer. Que voudriez-vous que les résultats soient? – katrielalex

+0

@Katrielalex - J'essaie d'obtenir les valeurs des nœuds - 1, "C:/Quelque chose", etc. Comment puis-je accomplir cela? Y a-t-il un meilleur moyen? Existe-t-il un moyen facile d'obtenir une sorte de dictionnaire ou d'objet avec les noms de noeud et les valeurs? – froadie

+0

Voir ci-dessous. Malheureusement, il n'y a pas de moyen par défaut de le convertir en dictionnaire, car le format XML est trop flexible pour qu'il y ait un moyen raisonnable de le faire. Vous devez câbler les indices des nœuds (par exemple, que se passerait-il s'il y avait deux nœuds 'exitCode'?) – katrielalex

Répondre

3

Est-ce que cela aide?

doc = '''<Response> 
    <exitCode>1</exitCode> 
    <fileName>C:/Something/</fileName> 
    <errors> 
     <error>Error generating report</error> 
    </errors> 
</Response>''' 

from xml.dom import minidom 

something = minidom.parseString(doc) 

nodeList = [ ] 
for node in something.getElementsByTagName("Response"): 
    response = { } 
    response[ "exit code" ] = node.getElementsByTagName("exitCode")[ 0 ].childNodes[ 0 ].nodeValue 
    response[ "file name" ] = node.getElementsByTagName("fileName")[ 0 ].childNodes[ 0 ].nodeValue 
    errors = node.getElementsByTagName("errors")[ 0 ].getElementsByTagName("error") 
    response[ "errors" ] = [ error.childNodes[ 0 ].nodeValue for error in errors ] 

    nodeList.append(response) 

import pprint 
pprint.pprint(nodeList) 

cède

[{'errors': [u'Error generating report'], 
    'exit code': u'1', 
    'file name': u'C:/Something/'}] 
+0

Cela fonctionne pour cet exemple spécifique, mais je cherchais quelque chose d'un peu plus générique qui pourrait analyser n'importe quel fichier xml dans une sorte de structure Python ... – froadie

+1

@froadie: Cette fonction existe déjà; C'est ce qu'on appelle 'xml.dom.minidom.parse'. Il n'y a pas de structure Python intégrée qui puisse représenter adéquatement XML, donc elle définit ses propres structures. – katrielalex

+1

Ceci est une excellente solution au problème. Si vous voulez quelque chose de plus robuste, vous pouvez aller avec 'xml.etree.ElementTree' sur' xml.dom.minidom', car cela implique moins de syntaxe avec les parcours imbriqués. – jathanism

0

Vous ne pensez pas à XML du point de vue DOM. A savoir, 'C:/Something' n'est pas la valeur de noeud de l'élément dont la variable est 'fileName'; c'est la valeur de noeud du noeud de texte qui est le premier enfant de l'élément dont la variable est 'nomFichier'.

Ce que je vous recommande de faire est de jouer avec un peu plus en python lui-même: démarrer python.

de minidom d'importation xml.dom

x = minidom.parseString ('< réponse > <filename> C:/</filename> >')

x.getElementsByTagName ('Réponse') ... x.getElementsByTagName ('Response') [0] .childNodes [0] ...

et ainsi de suite. Vous obtiendrez une appréciation rapide de la façon dont le document est analysé.

3

Si vous êtes débutant avec XML et Python, et avez aucune raison impérieuse d'utiliser DOM, je vous suggère fortement de jeter un oeil à l'api ElementTree (mis en œuvre dans la bibliothèque standard xml.etree.ElementTree)

Pour donner vous un avant-goût:

import xml.etree.cElementTree as etree 

tree = etree.parse('C:/XMLTest.xml') 
response = tree.getroot() 
exitcode = response.find('exitCode').text 
filename = response.find('fileName').text 
errors = [i.text for i in response.find('errors')] 

(si vous avez besoin plus de puissance - XPath, validation, xslt etc ... - vous pouvez même passer à lxml, qui met en œuvre la même API, mais avec beaucoup d'extras)

0

Je recommande mon ibrary xml2obj. C'est beaucoup plus propre que DOM. La "bibliothèque" a seulement 84 lignes de code que vous pouvez intégrer n'importe où.

In [185]: resp = xml2obj(something) 

In [186]: resp.exitCode 
Out[186]: u'1' 

In [187]: resp.fileName 
Out[187]: u'C:/Something/' 

In [188]: len(resp.errors) 
Out[188]: 1 

In [189]: for node in resp.errors: 
    .....:  print node.error 
    .....: 
    .....: 
Error generating report 
Questions connexes