2008-11-25 21 views
90

Estoy creando una interfaz gráfica de usuario para Eve Online API en Python.Obtiene el valor Element con minidom con Python

He sacado con éxito los datos XML de su servidor.

Estoy tratando de agarrar el valor de un nodo denominado "nombre":

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

Esto parece encontrar el nodo, pero la salida es a continuación:

[<DOM Element: name at 0x11e6d28>] 

cómo podría conseguir para imprimir el valor del nodo?

+3

Está empezando a parecer que la respuesta a la mayoría de las preguntas "minidom" es "use ElementTree". –

Respuesta

123

Debe ser sólo

name[0].firstChild.nodeValue 
+3

Cuando nombro [0] .nodeValue devuelve "Ninguno", solo para probar, le pasé el nombre [0] .nodeName y me dio el "nombre" que es correcto. ¿Algunas ideas? – RailsSon

+27

¿Qué pasa con el nombre [0] .firstChild.nodeValue? – eduffy

+7

Solo ten en cuenta que no dependes de los detalles de implementación en el generador de xml. No hay garantías de que el primer hijo sea * el * nodo de texto ni el * único * nodo de texto en los casos en que pueda haber más de un nodo secundario. –

54

Probablemente algo como esto si es la parte del texto que quieres ...

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 parte de texto de un nodo se considera un nodo en sí mismo colocado como un nodo hijo del que usted solicitó. Por lo tanto, querrá revisar todos sus elementos secundarios y encontrar todos los nodos secundarios que son nodos de texto. Un nodo puede tener varios nodos de texto; p.ej.

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

Desea tanto "blabla" como "znylpx"; de ahí el "" .join(). Es posible que desee reemplazar el espacio con una nueva línea más o menos, o tal vez por nada.

+9

Tiene que haber una llamada incorporada para eso. –

+0

Buena respuesta. Lo hicieron mucho más complicado de lo necesario. – patros

6

Sé que esta pregunta es bastante viejo, pero pensé que podría tener un tiempo más fácil con 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 

Yo sé que no es muy específica, pero acabo de descubrir que, y hasta ahora es mucho más fácil de entender que el minidomo (dado que muchos nodos son esencialmente espacios en blanco).

Por ejemplo, usted tiene el nombre de la etiqueta y el texto real juntos, como era de esperar, probablemente:

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

se puede usar algo como this.It funcionó para mí

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 
2

tuve un caso similar, lo que funcionó para mí fue:

name.firstChild.childNodes [0] .DATA

Se supone que XML es simple y realmente lo es, y no sé por qué el minidomo de python lo hizo tan complicado ... pero así es como está hecho

2

Aquí hay una respuesta ligeramente modificada de Henrik para nodos múltiples (es decir.cuando getElementsByTagName devuelve más de una ocasión)

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

esto debería funcionar:

from xml.dom.minidom import parse 

doc = minidom.parseString("C:\\eve.xml") 
name = doc.getElementsByTagName('name') 
print(name) 
4

La respuesta anterior es correcta, a saber:

name[0].firstChild.nodeValue 

Sin embargo, para mí, al igual que los demás, mi valor estaba más abajo en el árbol:

name[0].firstChild.firstChild.nodeValue 

Para ello he utilizado el siguiente:

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) 

La ejecución de este para mi sencilla Imagen SVG creado con Inkscape esto me dio:

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:() 

Solía ​​xml.dom.minidom, los diversos campos son explained on this page, MiniDom Python.

Cuestiones relacionadas