使用Python最小化获取元素值


109

我正在使用Python创建Eve Online API的GUI前端。

我已经成功地从他们的服务器中提取了XML数据。

我正在尝试从名为“名称”的节点获取值:

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

这似乎找到了节点,但是输出如下:

[<DOM Element: name at 0x11e6d28>]

我如何获得它来打印节点的值?


5
看起来大多数“微小”问题的答案就是“使用ElementTree”。
沃伦·P

Answers:


156

应该只是

name[0].firstChild.nodeValue

4
当我执行name [0] .nodeValue时返回“ None”,只是为了测试,我通过了name [0] .nodeName并给了我“正确的名称”。有任何想法吗?
RailsS​​on

28
那name [0] .firstChild.nodeValue呢?
eduffy

7
请注意,您不依赖xml-generator中的实现细节。有没有保证了第一个孩子是文本节点也不是唯一在任何情况下,文本节点那里可以超过一个子节点。
Henrik Gustafsson

53
为什么有人会设计一个库,其中<name> Smith </ name>的nodeValue不是“ Smith”?那个小金块花了我30分钟把头发扯掉。我现在秃顶。谢谢你
阿萨夫·拉维

10
仅仅是因为他们设计了与html一起使用的方式,以允许诸如<nodeA> Some Text <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 )

对使用Inkscape创建的简单SVG文件运行此命令,这给了我:

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] .data

XML应该很简单,实际上确实如此,我不知道为什么python的小巧性使它如此复杂...但是它是如何制作的


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.datafirstChild.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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.