1
I have the following structure

<root>
  <data>
     <config>
        CONFIGURATION
     <config>
  </data>

</root>

With Python's ElementTree module I want to add a parent element to <config> tag as

<root>
  <data>
    <type>
      <config>
        CONFIGURATION
      <config>
    </type>
  </data>

</root>

Also the xml file might have other config tags elsewhere but I'm only interested in the ones appearing under data tag.

mzjn
  • 48,958
  • 13
  • 128
  • 248

1 Answers1

5

This boils down to ~3 steps:

  1. get the elements that match your criteria (tag == x, parent tag == y)
  2. remove that element from the parent, putting a new child in that place
  3. add the former child to the new child.

For the first step, we can use this answer. Since we know we'll need the parent later, let's keep that too in our search.

def find_elements(tree, child_tag, parent_tag):
    parent_map = dict((c, p) for p in tree.iter() for c in p)
    for el in tree.iter(child_tag):
        parent = parent_map[el]
        if parent.tag == parent_tag:
            yield el, parent

steps two and three are pretty related, we can do them together.

def insert_new_els(tree, child_tag, parent_tag, new_node_tag):
    to_replace = list(find_elements(tree, child_tag, parent_tag))
    for child, parent in to_replace:
        ix = list(parent).index(child)
        new_node = ET.Element(new_node_tag)
        parent.insert(ix, new_node)
        parent.remove(child)
        new_node.append(child)

Your tree will be modified in place. Now usage is simply:

tree = ET.parse('some_file.xml')
insert_new_els(tree, 'config', 'data', 'type')
tree.write('some_file_processed.xml')

untested

Community
  • 1
  • 1
mgilson
  • 300,191
  • 65
  • 633
  • 696