Update root in XML after the childs got processed
<p>Related to <a href="http://stackoverflow.com/q/38974656/3316077">this SO question</a> I managed to accomplish what's been asked with the following snippet:</p>

<pre><code>import xml.etree.ElementTree as ET


def read_xml():
    with open('test.xml') as xml_file:
        return xml_file.read()


xml_file = read_xml()

root = ET.fromstring(xml_file)
pmt_infs = root.find('.//CstmrCdtTrfInitn').findall('PmtInf')
print(pmt_infs)

nodes = []
for node in pmt_infs:
    children = list(node)
    nodes.append(children)

xml_stuff = [None] * len(nodes)
to_remove = []

for first, *column in zip(*nodes):
    for index, item in enumerate(column, 1):
        if 'CdtTrfTxInf' in item.tag:
            xml_stuff[index] = item
            continue

        if first.tag == item.tag and first.text == item.text and index not in to_remove:
            to_remove.append(index)

for index in to_remove:
    pmt_infs[0].append(xml_stuff[index])
for index in to_remove[::-1]:
    pmt_infs.pop(index)

print(pmt_infs)
</code></pre>

<p>Now, what the above piece of code does it's exactly what I asked in the previous question:</p>

<blockquote>
  <p>I would like to move the whole <code>&lt;CdtTrfTxInf&gt;&lt;/CdtTrfTxInf&gt;</code> to the
  first <code>&lt;PmtInf&gt;&lt;/PmtInf&gt;</code> and remove the whole <code>&lt;PmtInf&gt;&lt;/PmtInf&gt;</code> that
  I've taken <code>&lt;CdtTrfTxInf&gt;&lt;/CdtTrfTxInf&gt;</code> from.</p>
</blockquote>

<p>The above has been done, but I have a small problem. Initially, I get the <code>root</code> from the file. And now, I want to update it with the new data. The problem is that I don't know how to add the first part of the XML in the new file and then, append the <code>pmt_infs</code> to it:</p>

<pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Document&gt;
    &lt;CstmrCdtTrfInitn&gt;
        &lt;GrpHdr&gt;
            &lt;other_tags&gt;a&lt;/other_tags&gt; &lt;!--here there might be other nested tags inside &lt;other_tags&gt;&lt;/other_tags&gt;--&gt;
            &lt;other_tags&gt;b&lt;/other_tags&gt; &lt;!--here there might be other nested tags inside &lt;other_tags&gt;&lt;/other_tags&gt;--&gt;
            &lt;other_tags&gt;c&lt;/other_tags&gt; &lt;!--here there might be other nested tags inside &lt;other_tags&gt;&lt;/other_tags&gt;--&gt;
        &lt;/GrpHdr&gt;
        &lt;!-- here should be the &lt;PmtInf&gt; that's been processed above --&gt;
    &lt;/CstmrCdtTrfInitn&gt;
&lt;/Document&gt; 
</code></pre>

<p>Can somebody give me some hints ?   </p>

<hr>

<p>LE: As requested, I'll add here the desired results:</p>

<pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Document&gt;
    &lt;CstmrCdtTrfInitn&gt;
        &lt;GrpHdr&gt;
            &lt;other_tags&gt;a&lt;/other_tags&gt; 
            &lt;other_tags&gt;b&lt;/other_tags&gt;
            &lt;other_tags&gt;c&lt;/other_tags&gt; 
        &lt;/GrpHdr&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;d&lt;/things&gt; 
            &lt;things&gt;e&lt;/things&gt; 

            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;f&lt;/things&gt; 
            &lt;things&gt;g&lt;/things&gt; 

            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;
    &lt;/CstmrCdtTrfInitn&gt;
&lt;/Document&gt;
</code></pre>

<p>Now the output looks like that because:</p>

<ul>
<li>looking at the <code>&lt;PmtInf&gt;&lt;/PmtInf&gt;</code> sections (which are three), we can see that:

<ol>
<li>if we compare the <code>&lt;things&gt;</code> from first <code>&lt;pmtinf&gt;</code> and things from the second <code>&lt;pmtinf&gt;</code> we can see they are not the same (<code>d != f</code>, <code>e != g</code>) so we move on to the next <code>&lt;pmtinf&gt;</code>; If we compare the first <code>&lt;pmtinf&gt;</code> <code>&lt;things&gt;</code> with the third ones, they are also the same, so we leave the first <code>&lt;pmtinf&gt;</code> as it is.</li>
<li>we go to the second <code>pmtinf</code> section and compare <code>things</code> from it with <code>things</code> from the third <code>pmtinf</code> (they are the same). That said, we take the <code>CdtTrfTxInf</code> part from the third <code>pmtinf</code>, add it to the second <code>pmtinf</code> at the end and remove the third <code>pmtinf</code> completely.</li>
</ol></li>
</ul>

<p>Imagine this as a list of lists (which in fact, that's what they are):</p>

<pre><code>[[a1, b1, c1], [a2, b2, c2], [a3, b3, c3]]
</code></pre>

<p><em>Where</em>:
a = first <code>&lt;things&gt;</code> tag from a <code>&lt;PmtInf&gt;</code>
b = second <code>&lt;things&gt;</code> tag from a <code>&lt;PmtInf&gt;</code>
c = <code>&lt; CdtTrfTxInf&gt;</code> tag from a <code>&lt;PmtInf&gt;</code></p>

<p>In my example:</p>

<p><code>a1!=a2</code> and <code>b1!=b2</code> => we can move to the next sublist (if they would've been the same, the list would look like:</p>

<pre><code>[[a1, b1, c1, c2],[a3, b3, c3]]
</code></pre>

<p><code>a1!=a3</code> and <code>b1!=b3</code> => we can go to the second sublist and compare it with all the sublists after it</p>

<p><code>a2==a3</code> and <code>b2==b3</code> => they are the same so we will now have:</p>

<pre><code>[[a1, b1, c1], [a2, b2, c2, c3]]
</code></pre>

<p>As it is, my result will only be:</p>

<pre><code>&lt;PmtInf&gt;
    &lt;things&gt;d&lt;/things&gt;
    &lt;things&gt;e&lt;/things&gt;

    &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
    &lt;/CdtTrfTxInf&gt;
&lt;/PmtInf&gt;

&lt;PmtInf&gt;
    &lt;things&gt;f&lt;/things&gt;
    &lt;things&gt;g&lt;/things&gt;

    &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
    &lt;/CdtTrfTxInf&gt;
    &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
    &lt;/CdtTrfTxInf&gt;
&lt;/PmtInf&gt;
</code></pre>

<p>But I need it to be:</p>

<pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Document&gt;
    &lt;CstmrCdtTrfInitn&gt;
        &lt;GrpHdr&gt;
            &lt;other_tags&gt;a&lt;/other_tags&gt; 
            &lt;other_tags&gt;b&lt;/other_tags&gt;
            &lt;other_tags&gt;c&lt;/other_tags&gt; 
        &lt;/GrpHdr&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;d&lt;/things&gt; 
            &lt;things&gt;e&lt;/things&gt; 

            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;f&lt;/things&gt; 
            &lt;things&gt;g&lt;/things&gt; 

            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;
    &lt;/CstmrCdtTrfInitn&gt;
&lt;/Document&gt;
</code></pre>

<p>Consider <a href="https://www.w3.org/Style/XSL/" rel="nofollow">XSLT</a>, the transformation language used to manipulate XML documents. Specifically, your re-ordering actually requires the <a href="http://www.jenitennison.com/xslt/grouping/muenchian.html" rel="nofollow">Muenchian Method</a>, a 1.0 procedure to index the XML document with a certain key and group child data accordingly (in 2.0 an easier <code>&lt;xsl:for-each-group&gt;</code> can be used). Here, the key used is the concatenation of the <code>&lt;things&gt;</code> nodes under <code>&lt;PmtInf&gt;</code>.</p>

<p>Python's third-party module, <code>lxml</code>, can run XSLT 1.0 scripts using the <a href="http://xmlsoft.org/libxslt/" rel="nofollow">libxslt</a> processor. Of course, Python can also call external processors like <a href="http://stackoverflow.com/tags/xslt/info">Saxon and Xalan</a> which these processors can run 2.0, even newer 3.0 scripts. In this solution, no <code>for</code> looping or <code>if</code> logic is needed. Also, use of <code>&lt;xsl:key&gt;</code> is more efficient as you create a hash table on the document content.</p>

<p><strong>Input XML</strong> </p>

<pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Document&gt;
    &lt;CstmrCdtTrfInitn&gt;
        &lt;GrpHdr&gt;
            &lt;other_tags&gt;a&lt;/other_tags&gt;
            &lt;other_tags&gt;b&lt;/other_tags&gt;
            &lt;other_tags&gt;c&lt;/other_tags&gt;
        &lt;/GrpHdr&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;d&lt;/things&gt;
            &lt;things&gt;e&lt;/things&gt;
            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;f&lt;/things&gt; 
            &lt;things&gt;g&lt;/things&gt; 
            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;

        &lt;PmtInf&gt;
            &lt;things&gt;f&lt;/things&gt; 
            &lt;things&gt;g&lt;/things&gt; 
            &lt;CdtTrfTxInf&gt;
                &lt;!-- other nested tags here --&gt;
            &lt;/CdtTrfTxInf&gt;
        &lt;/PmtInf&gt;
    &lt;/CstmrCdtTrfInitn&gt;
&lt;/Document&gt;    
</code></pre>

<p><strong>XSLT</strong> Script <em>(save as a separate .xsl or .xslt file; adjust key @use and its later references to actual)</em></p>

<pre><code>&lt;xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt;
  &lt;xsl:output version="1.0" encoding="UTF-8" indent="yes" /&gt;
  &lt;xsl:strip-space elements="*"/&gt;

  &lt;xsl:key name="pkey" match="PmtInf" use="concat(things[1], things[2])" /&gt;

  &lt;xsl:template match="/Document"&gt;
    &lt;xsl:copy&gt;
      &lt;xsl:apply-templates select="CstmrCdtTrfInitn"/&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;

  &lt;xsl:template match="CstmrCdtTrfInitn"&gt; 
   &lt;xsl:copy&gt;
    &lt;xsl:copy-of select="GrpHdr"/&gt;

    &lt;xsl:for-each select="PmtInf[count(. | key('pkey', concat(things[1], things[2])))]"&gt;
      &lt;xsl:copy&gt;
        &lt;xsl:copy-of select="things"/&gt;
        &lt;xsl:for-each select="key('pkey', concat(things[1], things[2]))"&gt;      
           &lt;xsl:copy-of select="CdtTrfTxInf"/&gt;       
        &lt;/xsl:for-each&gt;
      &lt;/xsl:copy&gt;
    &lt;/xsl:for-each&gt;

   &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;    
&lt;/xsl:transform&gt;
</code></pre>

<p><strong>Python</strong> Script</p>

<pre><code>import lxml.etree as ET

# LOAD XML AND XSL SOURCES
dom = ET.parse('Input.xml')
xslt = ET.parse('XSLTScript.xsl')

# TRANSFORM SOURCE DOCUMENT
transform = ET.XSLT(xslt)
newdom = transform(dom)

# OUTPUT TO FILE   
xmlfile = open('Output.xml', 'wb')
xmlfile.write(newdom)
xmlfile.close()
</code></pre>

<p><strong>Output</strong> XML</p>

<pre><code>&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;Document&gt;
  &lt;CstmrCdtTrfInitn&gt;
    &lt;GrpHdr&gt;
      &lt;other_tags&gt;a&lt;/other_tags&gt;
      &lt;other_tags&gt;b&lt;/other_tags&gt;
      &lt;other_tags&gt;c&lt;/other_tags&gt;
    &lt;/GrpHdr&gt;
    &lt;PmtInf&gt;
      &lt;things&gt;d&lt;/things&gt;
      &lt;things&gt;e&lt;/things&gt;
      &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
      &lt;/CdtTrfTxInf&gt;
    &lt;/PmtInf&gt;
    &lt;PmtInf&gt;
      &lt;things&gt;f&lt;/things&gt;
      &lt;things&gt;g&lt;/things&gt;
      &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
      &lt;/CdtTrfTxInf&gt;
      &lt;CdtTrfTxInf&gt;
        &lt;!-- other nested tags here --&gt;
      &lt;/CdtTrfTxInf&gt;
    &lt;/PmtInf&gt;
  &lt;/CstmrCdtTrfInitn&gt;
&lt;/Document&gt;
</code></pre>

python xml python-3.x