I am writing a Python xml (netconf) parser and the target goal is to get a rpc-reply xml from server, modify some items, and produce a minimal config .xml that can be then sent to the server.
When modifying the values in GUI i add the modified elements to a set, along with their ancestor elements and sibling elements which don't contain children, since that would be the content of "minimum viable" result file
example (shortened) xml that I'm processing:
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:a1cfef75-dba4-4fdf-81eb-8d5f65d35511">
<data>
<bridges xmlns="urn:ieee:std:802.1Q:yang:ieee802-dot1q-bridge">
<bridge>
(...)
</bridge>
</bridges>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>PORT_0</name>
<description>random</description>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<bridge-port xmlns="urn:ieee:std:802.1Q:yang:ieee802-dot1q-bridge">
(...)
</bridge-port>
</interface>
<interface>
(...)
</interface>
</interfaces>
<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
(...)
</keystore>
</data>
</rpc-reply>
I have found a problem while using .iter()
and .remove()
together, i.e. when I want to modify e.g. <description>, it removes only the <bridge> branch, and then the .iter()
loop does not go back to <interfaces>, or back to it's immediate ancestor, most likely due to the fact that I've already removed every information about ancestors. In other words, the .iter().
loop stops at first encountered "last leaf" element.
I'm using the following code to remove items, self.itemstokeep
is a set of etree.Element
to keep
for item in treecopy.iter():
if not item in self.itemstokeep:
if not item.getparent() == None:
item.getparent().remove(item)
else:
continue
Can you recommend any nice way to solve this or completely work around the problem?
The biggest difference from the answers I've found here so far is that I won't know which items to remove, only which ones to keep, and I won't always have the same input structure with exception of 2 top-level elements, which makes the usual 'xpath' approach complicated...
I've also thought about moving away from creating an itemstokeep
set and basically rebuilding a tree while the elements are modified, but if it seemed like a non-optimized solution since I would need to always check for duplicates among ancestors and iterate through tree a lot - but maybe I'm missing something there as well.
The posted answers did not work. In case anyone has a similar problem in the future, I've solved this by doing a workaround with 2 loops:
1st loop creates a "negative" of item set, i.e. set of items I want to remove, which is first defined as empty
deleteset = set()
2nd loop iterates through created set and removes previously defined elements
Thanks to Hermann12 comments to original question, I've also realized my mistake in another part of code - originally I did not use
deepcopy()
to createtreecopy
root element, which was causing another class of problems in the application.In case anyone stumbles on this thread in future I would still love to know if there's a way to force
.iter()
not to go into the no-longer existing tree branch once the element containing children is removed.