web-dev-qa-db-fra.com

Obtenir la valeur de l'élément avec minidom avec Python

Je crée une interface graphique pour l'API Eve Online en Python.

J'ai réussi à extraire les données XML de leur serveur.

J'essaie de récupérer la valeur d'un noeud appelé "nom":

from xml.dom.minidom import parse
dom = parse("C:\\eve.xml")
name = dom.getElementsByTagName('name')
print name

Cela semble trouver le noeud, mais le résultat est ci-dessous:

[<DOM Element: name at 0x11e6d28>]

Comment pourrais-je l'obtenir pour imprimer la valeur du nœud?

96
RailsSon

Il devrait juste être

name[0].firstChild.nodeValue
136
eduffy

Probablement quelque chose comme ceci si c'est la partie texte que vous voulez ...

from xml.dom.minidom import parse
dom = parse("C:\\eve.xml")
name = dom.getElementsByTagName('name')

print " ".join(t.nodeValue for t in name[0].childNodes if t.nodeType == t.TEXT_NODE)

La partie texte d'un nœud est considérée comme un nœud lui-même placé en tant que nœud enfant de celui que vous avez demandé. Ainsi, vous voudrez parcourir tous ses enfants et trouver tous les nœuds enfants qui sont des nœuds de texte. Un nœud peut avoir plusieurs nœuds de texte; par exemple.

<name>
  blabla
  <somestuff>asdf</somestuff>
  znylpx
</name>

Vous voulez à la fois 'blabla' et 'znylpx'; d'où le "" .join (). Vous voudrez peut-être remplacer l'espace par une nouvelle ligne ou presque, ou peut-être par rien.

56
Henrik Gustafsson

vous pouvez utiliser quelque chose comme ça.Il a travaillé pour moi

doc = parse('C:\\eve.xml')
my_node_list = doc.getElementsByTagName("name")
my_n_node = my_node_list[0]
my_child = my_n_node.firstChild
my_text = my_child.data 
print my_text
11
samaksh

Je sais que cette question est assez ancienne maintenant, mais je pensais que vous auriez peut-être plus de facilité avec ElementTree

from xml.etree import ElementTree as ET
import datetime

f = ET.XML(data)

for element in f:
    if element.tag == "currentTime":
        # Handle time data was pulled
        currentTime = datetime.datetime.strptime(element.text, "%Y-%m-%d %H:%M:%S")
    if element.tag == "cachedUntil":
        # Handle time until next allowed update
        cachedUntil = datetime.datetime.strptime(element.text, "%Y-%m-%d %H:%M:%S")
    if element.tag == "result":
        # Process list of skills
        pass

Je sais que ce n'est pas très spécifique, mais je viens de le découvrir, et jusqu'à présent, il est beaucoup plus facile de comprendre que le minidom (car de nombreux nœuds sont essentiellement des espaces).

Par exemple, vous avez le nom de la balise et le texte réel ensemble, comme vous vous en doutez probablement:

>>> element[0]
<Element currentTime at 40984d0>
>>> element[0].tag
'currentTime'
>>> element[0].text
'2010-04-12 02:45:45'e
7
LarrikJ

La réponse ci-dessus est correcte, à savoir:

name[0].firstChild.nodeValue

Cependant, pour moi, comme pour d’autres, ma valeur était plus loin dans l’arbre:

name[0].firstChild.firstChild.nodeValue

Pour trouver cela, j'ai utilisé ce qui suit:

def scandown( elements, indent ):
    for el in elements:
        print("   " * indent + "nodeName: " + str(el.nodeName) )
        print("   " * indent + "nodeValue: " + str(el.nodeValue) )
        print("   " * indent + "childNodes: " + str(el.childNodes) )
        scandown(el.childNodes, indent + 1)

scandown( doc.getElementsByTagName('text'), 0 )

L'exécution de ceci pour mon simple fichier SVG créé avec Inkscape m'a donné:

nodeName: text
nodeValue: None
childNodes: [<DOM Element: tspan at 0x10392c6d0>]
   nodeName: tspan
   nodeValue: None
   childNodes: [<DOM Text node "'MY STRING'">]
      nodeName: #text
      nodeValue: MY STRING
      childNodes: ()
nodeName: text
nodeValue: None
childNodes: [<DOM Element: tspan at 0x10392c800>]
   nodeName: tspan
   nodeValue: None
   childNodes: [<DOM Text node "'MY WORDS'">]
      nodeName: #text
      nodeValue: MY WORDS
      childNodes: ()

J'ai utilisé xml.dom.minidom, les différents champs sont expliqués sur cette page, MiniDom Python.

6
LazyBrush

Voici une réponse légèrement modifiée de Henrik pour plusieurs nœuds (c'est-à-dire lorsque getElementsByTagName renvoie plus d'une instance)

images = xml.getElementsByTagName("imageUrl")
for i in images:
    print " ".join(t.nodeValue for t in i.childNodes if t.nodeType == t.TEXT_NODE)
2
khany

J'ai eu un cas similaire, ce qui a fonctionné pour moi a été:

name.firstChild.childNodes [0] .data

XML est supposé être simple et il l'est vraiment et je ne sais pas pourquoi le minidom de python l'a si compliqué ... mais c'est comme ça que ça a été fait

2
robertzp

La réponse à la question est que ma contribution consiste à clarifier une chose qui peut confondre les débutants:

Certaines des réponses suggérées et correctes ont utilisé firstChild.data et d’autres ont utilisé firstChild.nodeValue à la place. Si vous vous demandez quelle est la différence entre eux, vous devez vous rappeler qu'ils font la même chose car nodeValue est simplement un alias pour data.

La référence à ma déclaration peut être trouvée sous forme de commentaire sur le code source de minidom :

#nodeValue est un alias pour data

0
Billal Begueradj