hoj*_*oju 55 python elementtree
我正在使用内置的Python ElementTree模块.访问子节点很简单,但父节点或兄弟节点呢? - 这可以在不遍历整棵树的情况下有效地完成吗?
Vin*_*jip 45
没有以parent
属性的形式直接支持,但您可以使用此处描述的模式来实现所需的效果.建议使用以下单行(从链接到帖子)为整个树创建子到父映射:
parent_map = dict((c, p) for p in tree.getiterator() for c in p)
Run Code Online (Sandbox Code Playgroud)
sup*_*gra 21
Vinay的答案应该仍然有效,但对于Python 2.7+和3.2+,建议采用以下方法:
parent_map = {c:p for p in tree.iter() for c in p}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
jos*_*ven 10
您可以...
在ElementTree中使用xpath 表示法.
<parent>
<child id="123">data1</child>
</parent>
xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]
Run Code Online (Sandbox Code Playgroud)
如使用查找方法(xml.etree.ElementTree)后获取父元素中所述,您将不得不间接搜索父对象。具有xml:
<a>
<b>
<c>data</c>
<d>data</d>
</b>
</a>
Run Code Online (Sandbox Code Playgroud)
假设您已将etree元素创建为xml
变量,则可以使用:
In[1] parent = xml.find('.//c/..')
In[2] child = parent.find('./c')
Run Code Online (Sandbox Code Playgroud)
导致:
Out[1]: <Element 'b' at 0x00XXXXXX>
Out[2]: <Element 'c' at 0x00XXXXXX>
Run Code Online (Sandbox Code Playgroud)
较高的家长会被发现为: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
Run Code Online (Sandbox Code Playgroud)
最后一个答案打破了所有的希望......
在这里粘贴我来自/sf/answers/3846077231/ 的回答:
我有一个类似的问题,我有点创意。事实证明,没有什么可以阻止我们自己添加亲子信息。一旦我们不再需要它,我们就可以稍后剥离它。
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())
Run Code Online (Sandbox Code Playgroud)