77

組み込みのPythonElementTreeモジュールを使用しています。子にアクセスするのは簡単ですが、親ノードまたは兄弟ノードはどうでしょうか。-これは、ツリー全体を横断することなく効率的に実行できますか?

4

10 に答える 10

62

属性の形で直接サポートするparentことはできませんが、ここで説明するパターンを使用して、目的の効果を実現できます。次のワンライナーが提案されています(リンク先の投稿からPython 3.8に更新)。メソッドを使用して、ツリー全体の子から親へのマッピングを作成しますxml.etree.ElementTree.Element.iter

parent_map = {c: p for p in tree.iter() for c in p}
于 2010-01-31T08:04:25.593 に答える
30

Vinayの答えは引き続き機能するはずですが、Python 2.7以降および3.2以降では、次のことが推奨されます。

parent_map = {c:p for p in tree.iter() for c in p}

getiterator()を優先して非推奨になりました。iter()新しいdictリスト内包表記コンストラクターを使用すると便利です。

次に、XMLドキュメントの作成中に、子が複数の親を持つ可能性がありますが、ドキュメントをシリアル化すると、これは削除されます。それが重要な場合は、これを試してみてください。

parent_map = {}
for p in tree.iter():
    for c in p:
        if c in parent_map:
            parent_map[c].append(p)
            # Or raise, if you don't want to allow this.
        else:
            parent_map[c] = [p]
            # Or parent_map[c] = p if you don't want to allow this
于 2013-11-21T21:31:37.460 に答える
22

...ElementTreeでxpath表記を使用できます。

<parent>
     <child id="123">data1</child>
</parent>

xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]
于 2015-10-22T12:18:20.943 に答える
9

検索メソッド(xml.etree.ElementTree)を使用した後に親要素を取得するで説明したように、親を間接的に検索する必要があります。xmlを持っている:

<a>
 <b>
  <c>data</c>
  <d>data</d>    
 </b>
</a>

etree要素をxml変数に作成したと仮定すると、次を使用できます。

 In[1] parent = xml.find('.//c/..')
 In[2] child = parent.find('./c')

その結果:

Out[1]: <Element 'b' at 0x00XXXXXX> 
Out[2]: <Element 'c' at 0x00XXXXXX>

上位の親は次のように検出されますsecondparent=xml.find('.//c/../..')<Element 'a' at 0x00XXXXXX>

于 2015-11-24T22:19:25.007 に答える
5

XPath'..'セレクターを使用して、3.5.3または3.6.1(少なくともOSXでは)で親ノードを取得することはできません。たとえば、インタラクティブモードでは次のようになります。

import xml.etree.ElementTree as ET
root = ET.fromstring('<parent><child></child></parent>')
child = root.find('child')
parent = child.find('..') # retrieve the parent
parent is None # unexpected answer True

最後の答えはすべての希望を破ります...

于 2018-07-04T07:56:12.977 に答える
5

https://stackoverflow.com/a/54943960/492336からの私の答えをここに貼り付けます:

私も同様の問題を抱えていて、少しクリエイティブになりました。親子関係情報を自分で追加することを妨げるものは何もないことがわかりました。不要になったら、後で削除できます。

def addParentInfo(et):
    for child in et:
        child.attrib['__my_parent__'] = et
        addParentInfo(child)

def stripParentInfo(et):
    for child in et:
        child.attrib.pop('__my_parent__', 'None')
        stripParentInfo(child)

def getParent(et):
    if '__my_parent__' in et.attrib:
        return et.attrib['__my_parent__']
    else:
        return None

# Example usage

tree = ...
addParentInfo(tree.getroot())
el = tree.findall(...)[0]
parent = getParent(el)
while parent:
    doSomethingWith(parent)
    parent = getParent(parent)
stripParentInfo(tree.getroot())
于 2019-03-01T11:46:52.770 に答える
2

から回答を得ました

https://towardsdatascience.com/processing-xml-in-python-elementtree-c8992941efd2

ヒント:XPath内で「...」を使用して、現在の要素の親要素を返します。


for object_book in root.findall('.//*[@name="The Hunger Games"]...'):
    print(object_book)
于 2021-01-03T21:27:52.303 に答える
1

lxmlを使用している場合、次の親要素を取得できました。

parent_node = next(child_node.iterancestors())

StopIteration要素に祖先がない場合、これにより例外が発生します。そのため、そのシナリオに遭遇する可能性がある場合は、それをキャッチする準備をしてください。

于 2014-12-04T04:04:37.947 に答える
-1

単一のsubElementの親が必要で、subElementのxpathもわかっている場合の別の方法。

parentElement = subElement.find(xpath+"/..")
于 2014-02-23T02:41:36.057 に答える
-2

19.7.2.2を見てください。セクション:サポートされているXPath構文..。

パスを使用してノードの親を検索します。

parent_node = node.find('..')
于 2017-12-13T23:29:22.220 に答える