Python ile minidom ile Element değerini alın


109

Python'da Eve Online API için bir GUI ön ucu oluşturuyorum.

XML verilerini sunucularından başarıyla aldım.

Değeri "isim" adlı bir düğümden almaya çalışıyorum:

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

Bu düğümü buluyor gibi görünüyor, ancak çıktı aşağıdadır:

[<DOM Element: name at 0x11e6d28>]

Düğümün değerini yazdırmasını nasıl sağlayabilirim?


5
Çoğu "minidom" sorusunun yanıtı "ElementTree'yi kullan" gibi görünmeye başladı.
Warren P

Yanıtlar:


156

Sadece olmalı

name[0].firstChild.nodeValue

4
[0] .nodeValue adını verdiğimde "None" geri veriyor, sadece test etmek için [0] .nodeName adını geçtim ve bana doğru olan "name" verdi. Herhangi bir fikir?
RailsSon

28
Peki ya name [0] .firstChild.nodeValue?
eduffy

7
Sadece xml oluşturucudaki uygulama ayrıntılarına güvenmediğinize dikkat edin. İlk çocuk olduğuna dair bir garanti yoktur metin düğümü ne de tek birden fazla çocuk düğüm olabilir herhangi durumlarda metin düğümü.
Henrik Gustafsson

53
Neden birisi <name> Smith </name> nodeValue değerinin "Smith" dışında bir şey olduğu bir kitaplık tasarlasın ki ?! O küçük külçe saçımı 30 dakikalığına yırtmaya mal oldu. Kelim şimdi. Teşekkürler minidom.
Assaf Lavie

10
Bu <nodeA> Some Text <nodeinthemiddle> __complex__structure__ </nodeinthemiddle> Biraz daha metin </nodeA> gibi öğelere izin vermek için html ile çalışacak şekilde tasarlama biçimlerinden dolayı, bu durumda nodeA'nın nodeValue karmaşık yapı dahil olmak üzere tüm metni veya sadece 2 metin düğümünü ve orta düğümü içermelidir. Bakmanın en güzel yolu değil ama neden yaptıklarını anlayabiliyorum.
Josh Mc

60

Muhtemelen bunun gibi bir şey, eğer istediğiniz metin kısmı ise ...

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)

Bir düğümün metin kısmı, kendi başına istediğiniz düğümün alt düğümü olarak yerleştirilmiş bir düğüm olarak kabul edilir. Böylece, tüm alt düğümlerini gözden geçirmek ve metin düğümleri olan tüm alt düğümleri bulmak isteyeceksiniz. Bir düğümün birkaç metin düğümü olabilir; Örneğin.

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

Hem 'blabla' hem de 'znylpx' istiyorsunuz; dolayısıyla "" .join (). Boşluğu bir satırsonu ya da başka bir satırla değiştirmek isteyebilirsiniz ya da belki hiçbir şeyle.


12

bunun gibi bir şey kullanabilirsin, benim için çalıştı

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

Bu sorunun şimdi oldukça eski olduğunu biliyorum, ancak ElementTree ile daha kolay zaman geçirebileceğinizi düşündüm.

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

Bunun süper spesifik olmadığını biliyorum, ama yeni keşfettim ve şu ana kadar kafamı çevirmek minidom'dan çok daha kolay (çünkü pek çok düğüm aslında beyaz boşluktur).

Örneğin, muhtemelen beklediğiniz gibi etiket adına ve gerçek metne sahipsiniz:

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

8

Yukarıdaki cevap doğrudur, yani:

name[0].firstChild.nodeValue

Ancak benim için diğerleri gibi, değerim ağacın altındaydı:

name[0].firstChild.firstChild.nodeValue

Bunu bulmak için aşağıdakileri kullandım:

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 )

Bunu Inkscape ile oluşturduğum basit SVG dosyam için çalıştırmak bana şunu verdi:

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

Xml.dom.minidom kullandım, çeşitli alanlar bu sayfada, MiniDom Python'da açıklanmıştır.


2

Benzer bir davam vardı, benim için işe yarayan şuydu:

name.firstChild.childNodes [0] .data

XML'in basit olması gerekiyordu ve gerçekten öyle ve python'un minidomunun bunu neden bu kadar karmaşık yaptığını bilmiyorum ... ama böyle yapıldı


2

İşte birden fazla düğüm için Henrik'in biraz değiştirilmiş cevabı (yani, getElementsByTagName birden fazla örnek döndürdüğünde)

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

2

Soru cevaplandı, benim katkım yeni başlayanların kafasını karıştırabilecek bir şeyi açıklığa kavuşturmaktan ibaret:

Önerilen ve doğru cevaplardan firstChild.databazıları kullanıldı ve diğerleri firstChild.nodeValueyerine kullanıldı . Aralarındaki farkın ne olduğunu merak ediyorsanız, aynı şeyi yaptıklarını hatırlamalısınız çünkü nodeValuesadece takma addır data.

İfademe yapılan referans , minidom'un kaynak kodu hakkında bir yorum olarak bulunabilir :

# nodeValueiçin bir takma addırdata


0

Bu bir ağaç ve iç içe geçmiş öğeler olabilir. Deneyin:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.