题
我使用内建的Python ElementTree的模块。是简单的儿童获得,但对于父母或兄弟节点? - ?可以这样无需遍历整个树有效地完成
解决方案
有是在一个parent
属性的形式没有直接的支持,但可以或许使用模式中描述的此处以实现期望的效果。以下单行建议(从链接到后),以创建一个子到父映射为一整棵树:
parent_map = dict((c, p) for p in tree.getiterator() for c in p)
其他提示
应该仍然工作,但为Python 2.7+ 3.2+及以下推荐的Vinay的答案:
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 ...
符号的ElementTree。
<parent>
<child id="123">data1</child>
</parent>
xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]
如获取父元素提到使用find后方法(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>
中的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
在最后的答案打破了所有的希望......
的另一种方式,如果只想单个子元素的父和也称为子单元的xpath的。
parentElement = subElement.find(xpath+"/..")
如果您正在使用lxml的,我是能够得到与以下父元素:
parent_node = next(child_node.iterancestors())
这将引发StopIteration
异常,如果元素没有祖先 - 因此准备捕获,如果你可能会碰到那种情况下
通过 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())