Creating dynamic variables for XML Parsing
<p>I'm incredibly new at this, and I've tried searching but nothing I've found has been able to work for me.</p>

<p>I have xml data that looks like this</p>

<pre><code>&lt;datainfo&gt;
   &lt;data&gt;
       &lt;info State="1" Reason="x" Start="01/01/2016 00:00:00.000" End="01/01/2016 02:00:00.000"&gt;&lt;/info&gt;
       &lt;info State="1" Reason="y" Start="01/01/2016 02:00:00.000" End="01/01/2016 02:01:00.000"&gt;
            &lt;moreinfo Start="01/01/2016 02:00:00.000" End="01/01/2016 02:00:30.000"/&gt;
            &lt;moreinfo Start="01/01/2016 02:00:30.000" End="01/01/2016 02:01:00.000"/&gt;
       &lt;/info&gt;
       &lt;info State="2" Start="01/01/2016 02:01:00.000" End="01/01/2016 02:10:00.000"&gt;&lt;/info&gt;
       ...
   &lt;/data&gt;
&lt;/datainfo&gt;
</code></pre>

<p>I want find how much time was spent in State {1,2,...} for reason {x,y,...} on a specific day and have that print to a .csv format to be latter read in excel. </p>

<p>The issue I'm having is I can't use static variables because there are hundreds of different states for hundreds of different reasons, and they change constantly. </p>

<p>If I'm not clear please tell me, I am brand new to this and really appreciate any and all help.</p>

<p>Edit: Here is what I currently have, hopefully this will clear up what I'm trying to do.</p>

<pre><code>from datetime import datetime
from lxml import etree as ET

def parseXML(file):
    handler = open(file, "r") 
    tree = ET.parse(handler)  
    info_list = tree.xpath('//info')
    root = tree.getroot()
    dictionary = {}
    info_len = len(info_list)

    for i in range(info_len):
         info=root[0][0][i]
         info_attribs = info.attrib
         end = info_attribs[u'End']
         start = info_attribs[u'Start']
         FMT = '%m/%d/%Y %H:%M:%S.%f'
         tdelta = datetime.strptime(end, FMT) - datetime.strptime(start, FMT)
         t_dif = (tdelta.total_seconds()) / 60
         try:
             dictionary[info_attribs[u'State'] + status_attribs[u'Reason']] = t_dif
         except:
             continue
</code></pre>

<p>I'm trying to iterate through each line, find the State and the reason, then add them to a dictionary. If the entry already exists for that state and reason, I want to add it to the current value.</p>

<p>Let me know if I should provide more info!</p>

<p>Edit #2:</p>

<p>The output I'm looking for would be in the form of a .csv, stuctured like this:</p>

<pre><code>State - Reason, [Total time spent in State 1 for x reason]
</code></pre>

<p>You can use a <em>defaultdict</em>  for recurring keys using lists as value, you can also filter the info nodes using an <em>xpath</em> to only find the nodes that have both of the <em>attributes</em> you want so no need for any except:</p>

<pre><code>x = """&lt;datainfo&gt;
   &lt;data&gt;
       &lt;info State="1" Reason="x" Start="01/01/2016 00:00:00.000" End="01/01/2016 02:00:00.000"&gt;&lt;/info&gt;
       &lt;info State="1" Reason="y" Start="01/01/2016 02:00:00.000" End="01/01/2016 02:01:00.000"&gt;
            &lt;moreinfo Start="01/01/2016 02:00:00.000" End="01/01/2016 02:00:30.000"/&gt;
            &lt;moreinfo Start="01/01/2016 02:00:30.000" End="01/01/2016 02:01:00.000"/&gt;
       &lt;/info&gt;
       &lt;info State="2" Start="01/01/2016 02:01:00.000" End="01/01/2016 02:10:00.000"&gt;&lt;/info&gt;
   &lt;/data&gt;
&lt;/datainfo&gt;"""

from collections import defaultdict
import lxml.etree as et
from datetime import datetime

FMT = '%m/%d/%Y %H:%M:%S.%f'
tree = et.fromstring(x)
d = defaultdict(list)

for node in tree.xpath("//data/info[@Reason and @State]"):
    state = node.attrib["State"]
    reason = node.attrib["Reason"]
    end = node.attrib["End"]
    start = node.attrib[u'Start']
    tdelta = datetime.strptime(end, FMT) - datetime.strptime(start, FMT)
    d[state, reason].append((tdelta.total_seconds()) / 60))

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

<p>Depending on how you want the data to look for recurring keys would determine how you wrote to the csv, if you wanted one row each:</p>

<pre><code>import csv
with open("out.csv", "w") as f:
    wr = csv.writer(f)
    for k,v in d.items():
        for val in v:
            wr.writerow([k] + val)
</code></pre>

<p>If you actually want to sum:</p>

<pre><code>d = defaultdict(float)

for node in tree.xpath("//data/info[@Reason and @State]"):
    state = node.attrib["State"]
    reason = node.attrib["Reason"]
    end = node.attrib["End"]
    start = node.attrib[u'Start']
    tdelta = datetime.strptime(end, FMT) - datetime.strptime(start, FMT)
    d[state, reason] += (tdelta.total_seconds()) / 60
</code></pre>

<p>Then:</p>

<pre><code>import csv
with open("out.csv", "w") as f:
    wr = csv.writer(f)
    wr.writerows(d.items())
</code></pre>

python xml python-3.x parsing lxml