Access Elementtree Node Parent Node

access ElementTree node parent node

There's no direct support in the form of a parent attribute, but you can perhaps use the patterns described here to achieve the desired effect. The following one-liner is suggested (updated from the linked-to post to Python 3.8) to create a child-to-parent mapping for a whole tree, using the method xml.etree.ElementTree.Element.iter:

parent_map = {c: p for p in tree.iter() for c in p}

Get parent element after using find method (xml.etree.ElementTree)

The xml.etree API only supports a limited version of XPath. The xml.etree docs for the .. XPath expression state:

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

Directly getting the parent element is not supported in the xml.etree API. I would therefore recommend to use lxml, where you can simply use getparent() to get the parent element:

elm = root.find('.//Element[@elmid="1234"]')
elm.getparent()

lxml also has a full XPath 1.0 implementation, so elem.xpath('..') would work as well.

Python xml etree find parent node by text of child

Here is how I solved this, if anyone is interested in doing this stuff in xml instead of lxml (why ever).

According to suggestion from

http://effbot.org/zone/element.htm#accessing-parents

import xml.etree.ElementTree as et

tree = et.parse(my_xmlfile)
root = tree.getroot()
access = root.find('access')

# ... snip ...

def iterparent(tree):
for parent in tree.getiterator():
for child in parent:
yield parent, child

# users = list of user-names that need new_group added
# iter through tupel and find the username
# alter xml tree when found

for user in users:
print "processing user: %s" % user
for parent, child in iterparent(access):
if child.tag == "name" and child.text == user:
print "Name found: %s" % user
parent.append(et.fromstring('<group>%s</group>' % new_group))

After this et.dump(tree) shows that tree now contains the correctly altered user-subtree with another group tag added.

Note: I am not really sure why this works, I just expect that yield gives a reference to the tree and therefore altering the parent yield returned alters the original tree. My python knowledge is not good enough to be sure about this tho. I just know that it works for me this way.

Finding parent from child in XML using python

You need to traverse one level up

for elem in things.iterfind('thing/nodes/node[@id="1"]'):
# get parent of node - nodes
print elem.getparent()
# get grand parent of node - thing
print elem.getparent().getparent()
# now lets get the thing id
print elem.getparent().getparent().attrib.get('id')

remove parent node depending on the child element values

If I understand you correctly, this is what you need to do:

fruits = """[your code above]"""
import xml.etree.ElementTree as ET
tree = ET.fromstring(fruits)
targets = tree.findall('.//b')
for target in targets:
f_list= [t.text for t in target.findall('.//d')]
if not "banana" in f_list:
tree.remove(target)
print(ET.tostring(tree).decode())

#to write to file:
tree = ET.ElementTree(tree)
tree.write("test.xml", encoding="utf-8")

Output:

<a>
<header>
fruit
</header>
<b>
<fruitlist>
<d>banana</d>
</fruitlist>
<fruitlist>
<d>apple</d>
</fruitlist>
</b>

<b>
<fruitlist>
<d>banana</d>
</fruitlist>
</b>
</a>

How to find Parent Node for Nested Element XML Tag, Python 3.6

We can get parent from lxml:

import pandas as pd
import requests
from lxml import etree
from io import StringIO, BytesIO

Dimension_Id = 'RDS_DICT_REGIONS_NSO'
Language = '1033'

Request_URL = 'http://dataportal.ins.tn/WebApi/GetDimensionElements'
Method_Post_Body = "<QueryMessage lcid='" + Language + "'> <DataWhere> <DimensionId>" + Dimension_Id + "</DimensionId> </DataWhere> </QueryMessage>"

Post_Response = requests.post(Request_URL, data=Method_Post_Body, headers={'Content-type': 'text/xml'})

XRoot_P = etree.fromstring(Post_Response.content)

XML_List = []
XML_Structure_All = pd.DataFrame()
for Tag_1 in XRoot_P[1]:
for Child in Tag_1.iter():
if len(Child.getparent().attrib) > 0:
if 'CODE' in Child.getparent().attrib.keys():
Parent = Child.getparent().attrib['CODE']
elif 'C_CODE' in Child.getparent().attrib.keys():
Parent = Child.getparent().attrib['C_CODE']
elif 'KEY' in Child.getparent().attrib.keys():
Parent = Child.getparent().attrib['KEY']
else:
Parent = ''

if 'CODE' in Child.attrib.keys(): Col = 'CODE'
elif 'C_CODE' in Child.attrib.keys(): Col = 'C_CODE'
elif 'KEY' in Child.attrib.keys(): Col = 'KEY'

XML_Dict = {'CODE': Child.attrib[Col], 'Parent': Parent}
XML_List.append(XML_Dict)
XML_Dimension_Parent = pd.DataFrame(XML_List)

access ElementTree node parent node

There's no direct support in the form of a parent attribute, but you can perhaps use the patterns described here to achieve the desired effect. The following one-liner is suggested (updated from the linked-to post to Python 3.8) to create a child-to-parent mapping for a whole tree, using the method xml.etree.ElementTree.Element.iter:

parent_map = {c: p for p in tree.iter() for c in p}

Get the entire parent tag's text in ElementTree

This is indeed a very awkward peculiarity of ElementTree. The gist is: if an element contains both text and child elements, and if a child element intervenes between different intermediate text nodes, the text after the child element is said to be this element's tail instead of its text.

In order to collect all text that is an immediate child or descendant of an element, you would need to access the text and tail of this element, and of all descendant elements.

>>> from lxml import etree

>>> s = '<p>This is the start of parent tag...<ref type="chlid1">child 1</ref>. blah1 blah1 blah1 <ref type="chlid2">child2</ref> blah2 blah2 blah2 </p>'

>>> root = etree.fromstring(s)
>>> child1, child2 = root.getchildren()

>>> root.text
'This is the start of parent tag...'

>>> child1.text, child1.tail
('child 1', '. blah1 blah1 blah1 ')

>>> child2.text, child2.tail
('child2', ' blah2 blah2 blah2 ')

As for a complete solution, I discovered that this answer is doing something very similar, that you can easily adapt to your usecase (by not printing the name of elements).


Edit: actually, the simplest solution by far, in my opinion, is to use itertext:

>>> ''.join(root.itertext())
'This is the start of parent tag...child 1. blah1 blah1 blah1 child2 blah2 blah2 blah2 '


Related Topics



Leave a reply



Submit