1

Why doesn't element.find("..") return root when root.findall("*") returns element?

def XML_Extract_Node_Tags(Tree, Node_Tags):
    """
    :param Tree: xml.etree.ElementTree
    :param Node_Tags: list
    :return: ReturnVal:
    """

    for el in Tree.findall("//"):
        if el.tag not in Node_Tags:
            print(el.tag)
            # Need to remove the element and set its children equal to parent
            for subel in el.findall("*"):
                ## Add subel to grandparent (if exists)
                grand_parent = subel.find('../..')
                if grand_parent:
                    # If it has a grand parent
                    grand_parent.append(subel)
            # Remove el from tree
            if not el.find(".."):
                print(el.tag, el.attrib)
            else:
                el.find("..").remove(el)

    ReturnVal = Tree
    return ReturnVal

First 5 lines of XML file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE build SYSTEM "build.dtd">
<build id="58" localAgents="true" cm="usl000348:80" start="6/1/2016 3:31:19 PM">
<properties>
<property name="CommandLine">emake all --emake-annodetail=waiting,registry,md5,lookup,history,file,env --emake-annofile=../Emake-2agents-1st.xml --emake-root=../</property>
Bob
  • 4,576
  • 7
  • 39
  • 107
  • `el.find('..')` means "in all child elements of this element, find the parent", right? Wouldn't that just point back to the element itself, instead of the element's parent? – John Gordon Jun 29 '16 at 18:47
  • @JohnGordon touche. Yes you're right: [Finds the first **subelement** matching match](https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.Element.find) – Bob Jun 29 '16 at 18:55
  • See also: http://stackoverflow.com/questions/2170610/access-elementtree-node-parent-node – Robᵩ Jun 29 '16 at 18:58

1 Answers1

2

Python's xml.etree.ElementTree implementation doesn't record the parent of an Element. Consequently, the documentation for XPath includes this:

.. Selects the parent element. Returns None if the path attempts to reach the ancestors of the start element (the element find was called on).

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • 1
    `lxml.etree.ElementTree` does keep track of parents, and may be a good alternative. I tested OPs syntax and it works as expected. – Jared Goguen Jun 29 '16 at 19:13
  • I was going to add that info to my answer, but couldn't word it right and find the right doc link. Feel free to edit, if you want. – Robᵩ Jun 29 '16 at 19:16