Pythonでminidomを使用して要素の値を取得する


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
ほとんどの「ミニドム」の質問に対する答えは「Use ElementTree」であるように見え始めています。
ウォーレンP

回答:


156

それだけです

name[0].firstChild.nodeValue

4
name [0] .nodeValueを実行すると、「None」が返されます。テストするために、name [0] .nodeNameを渡したところ、正しい「name」が得られました。何か案は?
RailsS​​on、2008年

28
name [0] .firstChild.nodeValueはどうですか?
エドゥフィ2008年

7
xml-generatorの実装の詳細に依存していないことに注意してください。最初の子であるという保証はありませんテキストノードでも唯一の複数の子ノードが存在することができる任意の場合はテキストノードが。
Henrik Gustafsson

53
<name> Smith </ name>のnodeValueが「Smith」以外のライブラリを設計するのはなぜですか?その小さなナゲットでは、髪を引き裂くのに30分かかりました。私は今ハゲです。ありがとう、minidom。
Assaf Lavie 2010年

10
これは、この<nodeA> Some Text <nodeinthemiddle> __ complex__structure __ </ nodeinthemiddle> Some more text </ nodeA>などの要素を許可するためにHTMLで動作するように設計された方法が原因です。この場合、nodeAのnodeValueと思いますか複雑な構造を含むすべてのテキスト、または単に2つのテキストノードと中間ノードを含む必要があります。それを見る最も良い方法ではありませんが、彼らがそれをした理由を私は見ることができます。
Josh Mc

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.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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.