Nhận giá trị phần tử với minidom bằng Python


109

Tôi đang tạo giao diện người dùng GUI cho API trực tuyến Eve bằng Python.

Tôi đã lấy thành công dữ liệu XML từ máy chủ của họ.

Tôi đang cố gắng lấy giá trị từ một nút có tên "name":

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

Điều này dường như tìm thấy nút, nhưng đầu ra là bên dưới:

[<DOM Element: name at 0x11e6d28>]

Làm cách nào tôi có thể làm cho nó in ra giá trị của nút?


5
Nó bắt đầu giống như câu trả lời cho hầu hết các câu hỏi "minidom" là "sử dụng ElementTree".
Warren P

Câu trả lời:


156

Nó chỉ nên là

name[0].firstChild.nodeValue

4
Khi tôi thực hiện tên [0] .nodeValue trả về "Không có", chỉ để kiểm tra, tôi đã chuyển cho nó tên [0] .nodeName và nó đã cho tôi "tên" chính xác. Bất kỳ ý tưởng?
RailsSon

28
Còn tên [0] .firstChild.nodeValue thì sao?
eduffy

7
Chỉ cần lưu ý rằng bạn không dựa vào chi tiết triển khai trong trình tạo xml. Có gì đảm bảo rằng đứa trẻ đầu tiên là các nút văn bản cũng không phải chỉ có nút văn bản trong bất kỳ trường hợp có thể có nhiều hơn một nút con.
Henrik Gustafsson

53
Tại sao mọi người lại thiết kế một thư viện trong đó nodeValue của <name> Smith </name> là bất cứ thứ gì ngoại trừ "Smith" ?! Cái thứ nhỏ bé đó khiến tôi mất 30 phút để xé tóc ra. Bây giờ tôi bị hói. Cảm ơn, minidom.
Assaf Lavie

10
Đó chỉ là do cách họ thiết kế nó hoạt động với html, để cho phép các phần tử như <nodeA> Một số văn bản <nodeinthemiddle> __complex__ Structure__ </nodeinthemiddle> Một số văn bản khác </nodeA>, trong trường hợp này, bạn có nghĩ là nodeValue của nodeA không nên chứa tất cả văn bản bao gồm cả cấu trúc phức tạp, hoặc đơn giản là 2 nút văn bản và nút giữa. Không phải là cách tốt nhất để xem xét nó, nhưng tôi có thể hiểu tại sao họ đã làm điều đó.
Josh Mc

60

Có thể là một cái gì đó như thế này nếu đó là phần văn bản bạn muốn ...

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)

Phần văn bản của một nút được coi là một nút tự nó được đặt làm nút con của nút mà bạn yêu cầu. Vì vậy, bạn sẽ muốn đi qua tất cả các nút con của nó và tìm tất cả các nút con là các nút văn bản. Một nút có thể có một số nút văn bản; ví dụ.

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

Bạn muốn cả 'blabla' và 'znylpx'; do đó "" .join (). Bạn có thể muốn thay thế khoảng trắng bằng một dòng mới hoặc lâu hơn, hoặc có thể không có gì.


12

bạn có thể sử dụng một cái gì đó như thế này. Nó làm việc cho tôi

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

Tôi biết câu hỏi này bây giờ khá cũ, nhưng tôi nghĩ bạn có thể có thời gian dễ dàng hơn với 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

Tôi biết điều đó không quá cụ thể, nhưng tôi mới phát hiện ra nó và cho đến nay, việc tìm hiểu nó dễ dàng hơn rất nhiều so với minidom (vì rất nhiều nút về cơ bản là khoảng trắng).

Ví dụ: bạn có tên thẻ và văn bản thực tế cùng nhau, giống như bạn có thể mong đợi:

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

8

Câu trả lời trên là đúng, cụ thể là:

name[0].firstChild.nodeValue

Tuy nhiên đối với tôi, cũng như những người khác, giá trị của tôi còn thấp hơn nhiều:

name[0].firstChild.firstChild.nodeValue

Để tìm cái này, tôi đã sử dụng như sau:

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 )

Chạy tệp này cho tệp SVG đơn giản của tôi được tạo bằng Inkscape, điều này đã cho tôi:

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

Tôi đã sử dụng xml.dom.minidom, các trường khác nhau được giải thích trên trang này, MiniDom Python.


2

Tôi đã gặp một trường hợp tương tự, điều phù hợp với tôi là:

name.firstChild.childNodes [0] .data

XML được cho là đơn giản và nó thực sự là như vậy và tôi không biết tại sao minidom của python lại làm nó phức tạp như vậy ... nhưng đó là cách nó được tạo ra


2

Đây là câu trả lời được sửa đổi một chút của Henrik cho nhiều nút (tức là khi getElementsByTagName trả về nhiều hơn một phiên bản)

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

2

Câu hỏi đã được trả lời, đóng góp của tôi bao gồm việc làm rõ một điều có thể khiến người mới bắt đầu bối rối:

Một số câu trả lời gợi ý và đúng được sử dụng firstChild.datavà những câu trả lời khác được sử dụng firstChild.nodeValuethay thế. Trong trường hợp bạn đang tự hỏi sự khác biệt giữa chúng, bạn nên nhớ rằng chúng làm điều tương tự vì nodeValuechỉ là bí danh cho data.

Tham chiếu đến tuyên bố của tôi có thể được tìm thấy dưới dạng nhận xét về mã nguồn của minidom :

# nodeValuelà bí danh chodata


0

Đó là một cái cây và có thể có các phần tử lồng vào nhau. Thử:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.