【问题标题】:Get Element value with minidom with Python使用 Python 以 minidom 获取元素值
【发布时间】:2010-09-23 23:06:54
【问题描述】:

我正在用 Python 为 Eve Online API 创建一个 GUI 前端。

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

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

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

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

[<DOM Element: name at 0x11e6d28>]

我怎样才能让它打印节点的值?

【问题讨论】:

  • 开始看起来大多数“minidom”问题的答案是“使用 ElementTree”。
  • Otoh,如果你学习 minidom 而不是 ElementTree,你可能需要更长的时间才能开始,但你将能够用你知道或最终学习的几乎任何其他编程语言做同样的事情,并且还能够利用许多其他工具。您付钱并做出选择。

标签: python dom minidom


【解决方案1】:

应该是

name[0].firstChild.nodeValue

【讨论】:

  • 当我做 name[0].nodeValue 时返回“None”,只是为了测试我通过了 name[0].nodeName 它给了我正确的“name”。有什么想法吗?
  • name[0].firstChild.nodeValue 怎么样?
  • 请注意,您不依赖于 xml 生成器中的实现细节。在可能有多个子节点的任何情况下,都不能保证第一个子节点是 文本节点或only 文本节点。
  • 为什么有人会设计一个库,其中 Smith 的 nodeValue 不是“Smith”?!那个小金块花了我 30 分钟的时间把头发扯下来。我现在秃了。谢谢,minidom。
  • 这只是因为他们将其设计为与 html 一起使用的方式,以允许诸如此 Some Text__complex__structure__Some more text 之类的元素,在这种情况下,您认为 nodeA 的 nodeValue 是否应该包含所有文本,包括复杂结构,或者只是 2 个文本节点和中间节点。不是最好的看待它的方式,但我可以理解他们为什么这样做。
【解决方案2】:

如果是你想要的文本部分,可能是这样的......

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()。您可能想用换行符左右替换空格,或者什么都不替换。

【讨论】:

    【解决方案3】:

    你可以使用这样的东西。它对我有用

    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
    

    【讨论】:

      【解决方案4】:

      我知道这个问题现在已经很老了,但我认为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
      

      我知道这不是特别具体,但我只是发现了它,到目前为止,它比 minidom 更容易理解(因为这么多节点本质上是空白)。

      例如,您将标签名称和实际文本放在一起,正如您可能期望的那样:

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

      【讨论】:

        【解决方案5】:

        上面的答案是正确的,即:

        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,各个字段都是explained on this page, MiniDom Python.

        【讨论】:

          【解决方案6】:

          这是 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)
          

          【讨论】:

            【解决方案7】:

            我有一个类似的案例,对我有用的是:

            name.firstChild.childNodes[0].data

            XML 应该是简单的,它确实是,我不知道为什么 python 的 minidom 做的这么复杂......但它是如何制作的

            【讨论】:

              【解决方案8】:

              问题已经得到解答,我的贡献在于澄清一件可能会让初学者感到困惑的事情:

              一些建议和正确的答案使用firstChild.data,而另一些则使用firstChild.nodeValue。如果您想知道它们之间有什么不同,您应该记住它们做同样的事情,因为nodeValue 只是data 的别名。

              可以在source code of minidom的评论中找到对我声明的引用:

              #nodeValuedata 的别名

              【讨论】:

                【解决方案9】:

                它是一棵树,可能有嵌套元素。试试:

                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
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-08-24
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多