python-访问ElementTree节点父节点
我正在使用内置的Python ElementTree模块。 访问子级很简单,但是父级或同级节点呢? -是否可以有效地完成而不遍历整个树?
hoju asked 2019-12-30T00:32:30Z
9个解决方案
44 votes
没有parent属性形式的直接支持,但是您也许可以使用此处描述的模式来实现所需的效果。 建议使用以下单行代码(从链接到文章)为整个树创建子到父映射:
parent_map = dict((c, p) for p in tree.getiterator() for c in p)
Vinay Sajip answered 2019-12-30T00:32:49Z
20 votes
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
supergra answered 2019-12-30T00:33:18Z
10 votes
您可以在ElementTree中使用xpath ...表示法。
data1
xml.findall('.//child[@id="123"]...')
>> []
josven answered 2019-12-30T00:33:38Z
5 votes
如使用查找方法(xml.etree.ElementTree)后获取父元素中所述,您将不得不间接搜索父对象。具有xml:
data
data
假设您已将etree元素创建为secondparent=xml.find('.//c/../..')变量,则可以使用:
In[1] parent = xml.find('.//c/..')
In[2] child = parent.find('./c')
导致:
Out[1]:
Out[2]:
高级父母将被发现为:secondparent=xml.find('.//c/../..')是
Vaasha answered 2019-12-30T00:34:11Z
3 votes
XPath'..'选择器不能用于在3.5.3或3.6.1(至少在OSX上)上检索父节点,例如在交互模式下:
import xml.etree.ElementTree as ET
root = ET.fromstring('')
child = root.find('child')
parent = child.find('..') # retrieve the parent
parent is None # unexpected answer True
最后一个答案打破了所有希望。
jlaurens answered 2019-12-30T00:34:36Z
2 votes
如果只想要一个subElement的父级,并且也知道subElement的xpath,则是另一种方式。
parentElement = subElement.find(xpath+"/..")
MK at Soho answered 2019-12-30T00:34:55Z
1 votes
如果您使用的是lxml,则可以使用以下命令获取父元素:
parent_node = next(child_node.iterancestors())
如果元素没有祖先,则将引发StopIteration异常-因此,如果您可能遇到这种情况,请准备好捕获该异常。
Shadow answered 2019-12-30T00:35:20Z
1 votes
将我的答案从[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())
sashoalm answered 2019-12-30T00:35:45Z
-1 votes
看一下19.7.2.2。 部分:支持的XPath语法...
使用以下路径查找节点的父节点:
parent_node = node.find('..')
Alf answered 2019-12-30T00:36:09Z