Holen Sie sich den Elementwert mit minidom mit Python


109

Ich erstelle ein GUI-Frontend für die Eve Online-API in Python.

Ich habe die XML-Daten erfolgreich von ihrem Server abgerufen.

Ich versuche, den Wert von einem Knoten namens "Name" abzurufen:

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

Dies scheint den Knoten zu finden, aber die Ausgabe ist unten:

[<DOM Element: name at 0x11e6d28>]

Wie kann ich den Wert des Knotens drucken lassen?


5
Es sieht so aus, als ob die Antwort auf die meisten "Minidom" -Fragen "ElementTree verwenden" lautet.
Warren P

Antworten:


156

Es sollte einfach so sein

name[0].firstChild.nodeValue

4
Wenn ich [0] benenne, gibt .nodeValue "None" zurück, nur um zu testen, habe ich ihm den Namen [0] .nodeName übergeben und mir "name" gegeben, was korrekt ist. Irgendwelche Ideen?
RailsSon

28
Was ist mit name [0] .firstChild.nodeValue?
Eduffy

7
Beachten Sie nur, dass Sie sich nicht auf Implementierungsdetails im XML-Generator verlassen. Es gibt keine Garantie dafür, dass das erste untergeordnete Element der Textknoten oder der einzige Textknoten ist, wenn mehr als ein untergeordneter Knoten vorhanden sein kann.
Henrik Gustafsson

53
Warum sollte jemand eine Bibliothek entwerfen, in der der Knotenwert von <name> Smith </ name> alles andere als "Smith" ist?! Dieses kleine Nugget hat mich 30 Minuten gekostet, mir die Haare auszureißen. Ich habe jetzt eine Glatze. Danke, Minidom.
Assaf Lavie

10
Es liegt nur an der Art und Weise, wie sie es für die Arbeit mit HTML entworfen haben, um Elemente wie diese <nodeA> Some Text <nodeinthemiddle> __complex__structure__ </ nodeinthemiddle> Some more text </ nodeA> zu berücksichtigen. In diesem Fall denken Sie, nodeA's nodeValue sollte den gesamten Text einschließlich der komplexen Struktur enthalten, oder einfach 2 Textknoten und den mittleren Knoten. Nicht die schönste Art, es zu betrachten, aber ich kann sehen, warum sie es getan haben.
Josh Mc

60

Wahrscheinlich so etwas, wenn es der gewünschte Textteil ist ...

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)

Der Textteil eines Knotens wird als Knoten an sich betrachtet, der als untergeordneter Knoten des von Ihnen angeforderten Knotens platziert wird. Daher möchten Sie alle untergeordneten Knoten durchgehen und alle untergeordneten Knoten finden, die Textknoten sind. Ein Knoten kann mehrere Textknoten haben. z.B.

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

Sie möchten sowohl 'blabla' als auch 'znylpx'; daher die "" .join (). Möglicherweise möchten Sie das Leerzeichen durch eine neue Zeile oder so oder durch nichts ersetzen.


12

Sie können so etwas verwenden. Es hat für mich geklappt

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

8

Ich weiß, dass diese Frage jetzt ziemlich alt ist, aber ich dachte, Sie könnten es mit ElementTree leichter haben

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

Ich weiß, dass das nicht sehr spezifisch ist, aber ich habe es gerade entdeckt, und bis jetzt ist es viel einfacher, meinen Kopf herumzukriegen als das Minidom (da so viele Knoten im Wesentlichen Leerzeichen sind).

Zum Beispiel haben Sie den Tag-Namen und den eigentlichen Text zusammen, genau wie Sie es wahrscheinlich erwarten würden:

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

8

Die obige Antwort ist richtig, nämlich:

name[0].firstChild.nodeValue

Für mich, wie für andere, war mein Wert jedoch weiter unten im Baum:

name[0].firstChild.firstChild.nodeValue

Um dies zu finden, habe ich Folgendes verwendet:

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 )

Das Ausführen für meine einfache SVG-Datei, die mit Inkscape erstellt wurde, gab mir Folgendes:

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

Ich habe xml.dom.minidom verwendet. Die verschiedenen Felder werden auf dieser Seite, MiniDom Python, erläutert.


2

Ich hatte einen ähnlichen Fall, was für mich funktionierte war:

name.firstChild.childNodes [0] .data

XML soll einfach sein und es ist wirklich so und ich weiß nicht, warum Pythons Minidom es so kompliziert gemacht hat ... aber so ist es gemacht


2

Hier ist eine leicht modifizierte Antwort von Henrik für mehrere Knoten (dh wenn getElementsByTagName mehr als eine Instanz zurückgibt)

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

2

Die Frage wurde beantwortet, mein Beitrag besteht darin, eine Sache zu klären, die Anfänger verwirren kann:

Einige der vorgeschlagenen und korrekten Antworten wurden verwendet, firstChild.dataandere firstChild.nodeValuestattdessen. Wenn Sie sich fragen, was der Unterschied zwischen ihnen ist, sollten Sie sich daran erinnern, dass sie dasselbe tun, da dies nodeValuenur ein Alias ​​für ist data.

Der Verweis auf meine Aussage kann als Kommentar zum Quellcode von minidom gefunden werden :

# nodeValueist ein Alias ​​fürdata


0

Es ist ein Baum, und es kann verschachtelte Elemente geben. Versuchen:

def innerText(self, sep=''):
    t = ""
    for curNode in self.childNodes:
        if (curNode.nodeType == Node.TEXT_NODE):
            t += sep + curNode.nodeValue
        elif (curNode.nodeType == Node.ELEMENT_NODE):
            t += sep + curNode.innerText(sep=sep)
    return t
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.