Python XML Parsing - Aligning Indexed Elements
<p>I am in dire need of some help on parsing an xml file. I have been spinning my wheels for a couple of weeks and have not made much progress. I have the below XML snippet and am trying to create a column with the names and values.  The problem is that some names are indexed and causing alignment issues when I print them side by side.</p>

<p>Can you please help or direct me to parsing this XML and get the desired print? Ideally I would like to do it without using lxml as the system does not have this module but do not mind suggestions using lxml as well.</p>

<p>XML File Example:</p>

<pre><code>&lt;root&gt;
  &lt;elments&gt;
    &lt;mgmtid&gt;
      &lt;date&gt;20160926&lt;/date&gt;
      &lt;gp&gt;3600&lt;/gp&gt;
      &lt;name p=""&gt;watermelons&lt;/name&gt;
      &lt;name p=""&gt;bananas&lt;/name&gt;
      &lt;name p=""&gt;oranges&lt;/name&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;None&lt;/objid&gt;
        &lt;value p=""&gt;10&lt;/value&gt;
        &lt;value p=""&gt;15&lt;/value&gt;
        &lt;value p=""&gt;20&lt;/value&gt;
      &lt;/valuegroup&gt;
    &lt;/mgmtid&gt;
    &lt;mgmtid&gt;
      &lt;date&gt;20160926&lt;/date&gt;
      &lt;gp&gt;3600&lt;/gp&gt;
      &lt;name p=""&gt;apples&lt;/name&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;red&lt;/objid&gt;
        &lt;value p=""&gt;100&lt;/value&gt;
      &lt;/valuegroup&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;blue&lt;/objid&gt;
        &lt;value p=""&gt;200&lt;/value&gt;
      &lt;/valuegroup&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;yellow&lt;/objid&gt;
        &lt;value p=""&gt;300&lt;/value&gt;
      &lt;/valuegroup&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;white&lt;/objid&gt;
        &lt;value p=""&gt;400&lt;/value&gt;
      &lt;/valuegroup&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;green&lt;/objid&gt;
        &lt;value p=""&gt;500&lt;/value&gt;
      &lt;/valuegroup&gt;
    &lt;/mgmtid&gt;
    &lt;mgmtid&gt;
      &lt;date&gt;20160926&lt;/date&gt;
      &lt;gp&gt;3600&lt;/gp&gt;
      &lt;name p=""&gt;strawberry&lt;/name&gt;
      &lt;name p=""&gt;guava&lt;/name&gt;
      &lt;valuegroup&gt;
        &lt;objid&gt;None&lt;/objid&gt;
        &lt;value p=""&gt;650&lt;/value&gt;
        &lt;value p=""&gt;750&lt;/value&gt;
      &lt;/valuegroup&gt;
    &lt;/mgmtid&gt;
  &lt;/elments&gt;
&lt;/root&gt;
</code></pre>

<p>My attempt (miserably failed) at getting names and values.  As you can see the values are not aligned with their names.</p>

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

tree = ET.parse('test_xml_file.xml')
root = tree.getroot()

names = []
values = []

for i in (tree.findall('.//')):
    if i.tag == 'name':
        n = (i.tag, i.text)
        names.append(n[0] + ' ' + str(n[1]))

for i in (tree.findall('.//')):
    if i.tag == 'value' or i.tag == 'objid':
        v = (i.tag, i.text)
        values.append(v[0] + ' ' + str(v[1]))

print('=' * 45)
for n, v in itertools.zip_longest(names, values):
    print(str(n).ljust(20, ' ') + str(v))
</code></pre>

<p>Current Output:</p>

<pre><code>name watermelons    objid None
name bananas        value 10
name oranges        value 15
name apples         value 20
name strawberry     objid red
name guava          value 100
None                objid blue
None                value 200
None                objid yellow
None                value 300
None                objid white
None                value 400
None                objid green
None                value 500
None                objid None
None                value 650
None                value 750
</code></pre>

<p>Desired Output:</p>

<pre><code>=============================
name        Index   value
=============================
watermelons None    10
bananas     None    15
oranges     None    20
apples      red     100
apples      blue    200
apples      yellow  300
apples      white   400
apples      green   500
strawberry  None    650
guava       None    750
</code></pre>

<p>I don't see a quick and fancy way of solving it, this code works:</p>

<pre><code>import xml.etree.ElementTree as ET
tree = ET.parse('test_xml_file.xml')
elements = []
mgmtids = tree.getroot().findall(".//mgmtid")
for mgmtid in mgmtids:
    names = mgmtid.findall(".//name")
    objids = mgmtid.findall(".//valuegroup/objid")
    values = mgmtid.findall(".//valuegroup/value")
    if len(names) == len(values):
        for i in range(len(names)):
            elements.append([names[i].text,objids[0].text,values[i].text])
    elif len(objids)==len(values):
        for i in range(len(values)):
            elements.append([names[0].text,objids[i].text,values[i].text])
    elif len(names) == len(objids):
        for i in range(len(names)):
            elements.append([names[i].text,objids[i].text,values[0].text])
        #elements.append([names[i].text,objids[i].text,values[i].text for i in len(names)])
print "\n".join([" - ".join([text for text in el]) for el in elements])
</code></pre>

<p>Hope it helps!</p>

python xml parsing xml-parsing lxml