代码之家  ›  专栏  ›  技术社区  ›  hoju

访问元素树节点父节点

  •  48
  • hoju  · 技术社区  · 15 年前

    我使用的是内置的python元素树模块。访问子节点很简单,但是父节点或兄弟节点呢?-这能在不遍历整个树的情况下有效地完成吗?

    9 回复  |  直到 5 年前
        1
  •  36
  •   Vinay Sajip    15 年前

    没有直接的支持 parent 属性,但您可能可以使用所描述的模式 here 达到预期效果。建议使用以下一行(从链接到日志)为整个树创建子到父映射:

    parent_map = dict((c, p) for p in tree.getiterator() for c in p)
    
        2
  •  15
  •   Community    7 年前

    Vinay's answer 应该仍然有效,但是对于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
    
        3
  •  7
  •   josven    9 年前

    可以使用xpath ... 元素树中的符号。

    <parent>
         <child id="123">data1</child>
    </parent>
    
    xml.findall('.//child[@id="123"]...')
    >> [<Element 'parent'>]
    
        4
  •  4
  •   Community    7 年前

    如中所述 Get parent element after using find method (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>

        5
  •  2
  •   MK at Soho    11 年前

    如果只需要一个子元素的父元素,还需要知道子元素的xpath,则可以使用另一种方法。

    parentElement = subElement.find(xpath+"/..")
    
        6
  •  1
  •   Shadow    6 年前

    如果您使用的是lxml,那么我可以使用以下内容获取父元素:

    parent_node = next(child_node.iterancestors())
    

    这将提高 StopIteration 如果元素没有祖先,则会出现异常-因此,如果遇到这种情况,请准备好捕获它。

        7
  •  0
  •   jlaurens    6 年前

    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
    

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

        8
  •  0
  •   sashoalm Yaser Kalali    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())
    
        9
  •  -2
  •   Alf    7 年前

    看19.7.2.2。章节: Supported XPath syntax

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

    parent_node = node.find('..')