Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - how to edit a specific XML element content when multiple element attributes of the same name exist?

I've been trying to edit one specific element content in an XML which contains multiple element contents of the same name, but the "for loop" which is required to set the element attribute will always go through the entire section and change them all.

Let's say that this is my XML:

<SectionA>
    <element_content attribute="device_1" type="parameter_1" />
    <element_content attribute="device_2" type="parameter_2" />
</SectionA>

I am currently using ElementTree with this code which works perfectly when a certain section has element content with different names, but it does not work for such a case - where the name is the same. It will simply change all of the content's attributes to have the same value.

for element in root.iter(section):
    print element
    element.set(attribute, attribute_value)

How do I access a specific element content and only change that one?

Bear in mind that I have no knowledge of the currently present attributes inside the element_content section, as I am dynamically adding them to a user's request.

Edit: Thanks to @leovp I was able to work around my problem and came up with this solution:

for step in root.findall(section):
    last_element = step.find(element_content+'[last()]')

last_element.set(attribute, attribute_value)

This causes the for loop to always change the last attribute in the specific nest. Since I am dynamically adding and editing lines, this makes it change the last one I have added.

Thank you.

like image 600
Kfir Cohen Avatar asked Mar 13 '26 03:03

Kfir Cohen


1 Answers

You can use limited XPath support that xml.etree provides:

>>> from xml.etree import ElementTree
>>> xml_data = """
... <SectionA>
...     <element_content attribute="device_1" type="parameter_1" />
...     <element_content attribute="device_2" type="parameter_2" />
... </SectionA>
... """.strip()
>>> tree = ElementTree.fromstring(xml_data)
>>> d2 = tree.find('element_content[@attribute="device_2"]')
>>> d2.set('type', 'new_type')
>>> print(ElementTree.tostring(tree).decode('utf-8'))
<SectionA>
    <element_content attribute="device_1" type="parameter_1" />
    <element_content attribute="device_2" type="new_type" />
</SectionA>

The most important part here is an XPath expression, where we find an element by its name AND attribute value:

d2 = tree.find('element_content[@attribute="device_2"]')

Update: since the XML data in question is not known beforehand. You can query the first, second, ..., last elements like this (indices start from 1):

tree.find('element_content[1]')
tree.find('element_content[2]')
tree.find('element_content[last()]')

But since you're iterating over elements anyway, the most simple solution is to just check current element's attributes:

for element in root.iter(section):
    if element.attrib.get('type') == 'parameter_2'):
        element.set(attribute, attribute_value)
like image 172
leovp Avatar answered Mar 14 '26 18:03

leovp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!