Отримайте значення Element за допомогою minidom з Python


109

Я створюю інтерфейс графічного інтерфейсу для Інтернет-інтерфейсу Eve в Python.

Я успішно витягнув XML-дані з їх сервера.

Я намагаюся схопити значення з вузла під назвою "name":

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

Це, здається, знаходить вузол, але вихід нижче:

[<DOM Element: name at 0x11e6d28>]

Як я міг змусити його надрукувати значення вузла?


5
Починає виглядати так, що відповідь на більшість питань "мінімуму" - це "використовувати ElementTree".
Warren P

Відповіді:


156

Це просто повинно бути

name[0].firstChild.nodeValue

4
Коли я роблю ім'я [0] .nodeValue повертає "None", просто для перевірки я передав йому ім'я [0] .nodeName, і це дало мені "ім'я", яке є правильним. Якісь ідеї?
RailsSon

28
А як з ім’ям [0] .firstChild.nodeValue?
eduffy

7
Будьте обережні, що ви не покладаєтесь на деталі реалізації у xml-генераторі. Там немає ніяких гарантій , що перша дитина текстовий вузол , ні тільки текстовий вузол в будь-яких випадках , коли може бути більше , ніж один дочірній вузол.
Генрік Густафссон

53
Чому хтось спроектував бібліотеку, в якій nodeValue <ім'я> Сміт </name> - це що інше, як "Сміт" ?! Цей маленький самородок коштував мені 30 хвилин на виривання волосся. Я зараз лисий. Спасибі, мінідом.
Ассаф Лав'є

10
Це лише завдяки тому, як вони створили його для роботи з html, щоб дозволити для таких елементів, як ця <nodeA> деякий текст <nodeinthemiddle> __complex__structure__ </nodeinthemiddle> Ще якийсь текст </nodeA>, в цьому випадку ви вважаєте, nodeA nodeValue повинен містити весь текст, включаючи складну структуру, або просто 2 текстові вузли та середній вузол. Не найприємніший спосіб поглянути на це, але я бачу, чому вони це зробили.
Джош Мак

60

Можливо, щось подібне, якщо це текстова частина, яку ви хочете ...

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)

Текстова частина вузла вважається вузлом, який сам по собі розміщується як дочірній вузол того, про кого ви попросили. Таким чином, вам потрібно буде пройти всіх його дітей і знайти всі дочірні вузли, які є текстовими вузлами. Вузол може мати кілька текстових вузлів; напр.

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

Ви хочете і "blabla", і "znylpx"; звідси "" .join (). Можливо, ви захочете замінити простір новим рядком чи так, а може, нічим.


12

ви можете використовувати щось подібне. Це для мене спрацювало

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

Я знаю, що це питання зараз досить старе, але я подумав, що вам може бути легше провести час з 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

Я знаю, що це не надто конкретно, але я щойно це виявив, і поки що набагато простіше обійти голову, ніж мінідом (оскільки стільки вузлів - це по суті білий простір).

Наприклад, у вас є ім’я тегу та власне текст разом, як ви, напевно, очікували:

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

8

Наведена відповідь правильна, а саме:

name[0].firstChild.nodeValue

Однак для мене, як і для інших, моє значення було далі по дереву:

name[0].firstChild.firstChild.nodeValue

Щоб знайти це, я використав наступне:

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 )

Запустивши це для мого простого файлу SVG, створеного за допомогою Inkscape, це дало мені:

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, на цій сторінці пояснюються різні поля , MiniDom Python.


2

У мене був подібний випадок, що для мене спрацювало:

name.firstChild.childNodes [0] .дані

XML повинен бути простим, і він насправді є, і я не знаю, чому мінітон пітона зробив це так складно ... але як це зробити


2

Ось дещо змінена відповідь Henrik на кілька вузлів (тобто коли getElementsByTagName повертає більше ніж один примірник)

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

2

На запитання відповіли, мій внесок полягає в з'ясуванні однієї речі, яка може бентежити початківців:

Деякі із запропонованих і правильних відповідей використовуються, firstChild.dataа інші використовуються firstChild.nodeValueзамість цього. Якщо вам цікаво, чим вони відрізняються, вам слід пам’ятати, що вони роблять те саме, тому що nodeValueце лише псевдонім data.

Посилання на мою заяву можна знайти як коментар до вихідного коду minidom :

# nodeValue- псевдонім дляdata


0

Це дерево, і там можуть бути вкладені елементи. Спробуйте:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.