Python 访问元素树节点父节点

Python 访问元素树节点父节点,python,elementtree,Python,Elementtree,我正在使用内置的Python ElementTree模块。访问子节点很简单,但是父节点或同级节点呢这可以在不遍历整个树的情况下高效地完成吗?没有以父属性的形式提供的直接支持,但是您可以使用所描述的模式来实现所需的效果。建议使用以下一行代码(从LinkedtoPosttoPython 3.8更新)为整个树创建子到父映射,方法如下: 没有以父属性的形式提供直接支持,但是您可能可以使用所描述的模式来实现所需的效果。建议使用以下一行代码(从LinkedtoPosttoPython 3.8更新)为整个树创

我正在使用内置的Python ElementTree模块。访问子节点很简单,但是父节点或同级节点呢这可以在不遍历整个树的情况下高效地完成吗?

没有以
父属性的形式提供的直接支持,但是您可以使用所描述的模式来实现所需的效果。建议使用以下一行代码(从LinkedtoPosttoPython 3.8更新)为整个树创建子到父映射,方法如下:


没有以
父属性的形式提供直接支持,但是您可能可以使用所描述的模式来实现所需的效果。建议使用以下一行代码(从LinkedtoPosttoPython 3.8更新)为整个树创建子到父映射,方法如下:

应该仍然可以工作,但对于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
应该仍然可以工作,但对于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

另一种方法是只需要一个子元素的父元素,也知道子元素的xpath

parentElement = subElement.find(xpath+"/..")

另一种方法是只需要一个子元素的父元素,也知道子元素的xpath

parentElement = subElement.find(xpath+"/..")

如果您使用的是lxml,我可以通过以下方式获得父元素:

parent_node = next(child_node.iterancestors())

如果元素没有祖先,这将引发一个
StopIteration
异常-因此,如果您可能遇到这种情况,请准备好捕捉它。

如果您使用lxml,我可以通过以下方式获得父元素:

parent_node = next(child_node.iterancestors())

如果元素没有祖先,这将引发一个
StopIteration
异常-因此,如果您可能遇到这种情况,请准备好捕捉它。

您可以在ElementTree中使用xpath
表示法

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

xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]

数据1
xml.findall('.//child[@id=“123”]…)
>> []

您可以在ElementTree中使用xpath
表示法

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

xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]

数据1
xml.findall('.//child[@id=“123”]…)
>> []
如中所述,您必须对父项进行间接搜索。 具有xml:

<a>
 <b>
  <c>data</c>
  <d>data</d>    
 </b>
</a>
导致:

Out[1]: <Element 'b' at 0x00XXXXXX> 
Out[2]: <Element 'c' at 0x00XXXXXX>
Out[1]:
出[2]:
较高的父级将被发现为:
secondparent=xml.find('.//.c/..')
如中所述,必须对父级进行间接搜索。 具有xml:

<a>
 <b>
  <c>data</c>
  <d>data</d>    
 </b>
</a>
导致:

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

更高的父级将被发现为:
secondparent=xml.find('.//./..')
查看19.7.2.2。节:

使用以下路径查找节点的父节点:

parent_node = node.find('..')

看看19.7.2.2。节:

使用以下路径查找节点的父节点:

parent_node = node.find('..')

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
将xml.etree.ElementTree作为ET导入
root=ET.fromstring(“”)
child=root.find('child')
parent=child.find(“..”)#检索父级
父项为无,意外答案为真

最后一个答案打破了所有希望…

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
将xml.etree.ElementTree作为ET导入
root=ET.fromstring(“”)
child=root.find('child')
parent=child.find(“..”)#检索父级
父项为无,意外答案为真

最后一个答案让人失望…

将我的答案粘贴在这里:

我有一个类似的问题,我有点创造性。事实证明,没有什么能阻止我们自己添加亲子关系信息。一旦我们不再需要它,我们就可以把它剥掉

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

将我的答案粘贴在这里:

我有一个类似的问题,我有点创造性。事实证明,没有什么能阻止我们自己添加亲子关系信息。一旦我们不再需要它,我们就可以把它剥掉

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())
我得到了他的答复

提示:在XPath中使用“…”返回当前元素的父元素。


对于root.findall('./*[@name=“The Hunger Games”]…')中的对象书:
打印(对象书)

提示:在XPath中使用“…”返回当前元素的父元素。


对于root.findall('./*[@name=“The Hunger Games”]…')中的对象书:
打印(对象书)

See-See对我不起作用,如果我只使用
subElement.find(“..”)
,我会得到“None”-一样的结果。假设一个名为
xpath
的变量已经存在,所以它对大多数人没有帮助。对我不起作用,如果我只使用
subElement.find(“..”),我会得到“None”-一样的结果
。假设名为
xpath
的变量已经存在,因此对大多数人没有帮助。如果您没有访问该树的权限,该怎么办?就像在.find()之后一样,如果不保存对根节点的引用,我不知道如何获取根节点(以及父节点/祖先节点)。但是我不明白
.find()
与此有什么关系。我只是用
.find()
作为一个示例函数,它只返回一个元素,如果您没有访问树的权限怎么办?就像在.find()之后一样,如果不保存对根节点的引用,我不知道如何获取根节点(以及父节点/祖先节点)。但我知道