Python Parse XML file for certain lines and output the line to Text widget
<p>I need to search a windows msinfo file (.nfo) for certain lines and print them to a Text widget. I can <code>print(line)</code> ever line in the file and I can output every line to the Text widget but as soon as I try to specify lines to output it stops working. I assume this is because the file is an XML but the XML parsing tools I see for python seem to look for lines like data=blah. The entries im looking for look like this when I open them in a txt editor:</p>

<pre><code>    &lt;Category name="Disks"&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Description]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[Disk drive]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Manufacturer]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[(Standard disk drives)]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Model]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[TOSHIB  MK1652GSX SCSI Disk Device]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Bytes/Sector]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[512]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Media Loaded]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[Yes]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Media Type]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[Fixed hard disk]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partitions]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[2]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[SCSI Bus]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[1]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[SCSI Logical Unit]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[0]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[SCSI Port]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[0]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[SCSI Target ID]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[0]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Sectors/Track]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[63]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Size]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[149.05 GB (160,039,272,960 bytes)]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Total Cylinders]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[19,457]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Total Sectors]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[312,576,705]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Total Tracks]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[4,961,535]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Tracks/Cylinder]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[255]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[Disk #1, Partition #0]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition Size]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[117.19 GB (125,830,301,184 bytes)]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition Starting Offset]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[32,256 bytes]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[Disk #1, Partition #1]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition Size]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[31.85 GB (34,200,714,240 bytes)]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
&lt;Item&gt;&lt;![CDATA[Partition Starting Offset]]&gt;&lt;/Item&gt;
&lt;Value&gt;&lt;![CDATA[125,830,333,440 bytes]]&gt;&lt;/Value&gt;
&lt;/Data&gt;
&lt;Data&gt;
</code></pre>

<p>I found a <a href="http://stackoverflow.com/questions/34070729/parse-a-nfo-file-with-python/34071854">post</a> asking for what I want but the solution doesn't work. The ET.parse is not found:</p>

<pre><code>import xml.etree as ET
file = 'D:\\MsInfo\\msinfo.nfo'
tree = ET.parse(file)
root = tree.getroot()

for element in root.findall('Category'):
    value = element.find('Data')
    for child in value:
        print(child.tag ,":",child.text)
</code></pre>

<p>When using the above I get this:</p>

<blockquote>
  <p>"C:\Program Files (x86)\Python35-32\python.exe" "D:/MY
  STUFF/Programming/Python/testing.py" Traceback (most recent call
  last):   File "D:/MY STUFF/Programming/Python/testing.py", line 3, in
  
      tree = ET.parse(file) AttributeError: module 'xml.etree' has no attribute 'parse'</p>
  
  <p>Process finished with exit code 1</p>
</blockquote>

<p>This is a snippet from my code:</p>

<pre><code>try:
    u = find("msinfo.nfo", s)
    for i in u:
        cpfotxt.insert('end', i + "\n")
        cpfotxt.yview(END)
        cpfotxt.insert('end', "================================= \n")
        with open(i, "r") as f:
            r = f.readlines()
            for line in r:
                if "Model" in line:
                    cpfotxt.insert('end', line + "\n")
</code></pre>

<p>If I remove the <code>if "Model" in line:</code> then it will dump everything into the Text widget fine.</p>

<p>This is how they look when opened normally with on windows:<p>
<a href="http://i.stack.imgur.com/cx4UV.png" rel="nofollow"><img src="http://i.stack.imgur.com/cx4UV.png" alt="enter image description here"></a></p>

<p>Any advice on how to pull lines I need from an nfo/XML file? </p>

<p>Also, when printing lines from an xml the font is bigger and double spaced. How can I make the line print the same way it would from a normal txt file? </p>

<p>So you need to understand the structure of the XML and then use the actual tags you're looking for instead of 'Data'</p>

<pre><code>    item = element.find('Item') 
    print(item.tag ,":",item.text)
    value = element.find('Value') 
    print(value.tag ,":",value.text)
</code></pre>

<p>Your actual problem is that you need to change the import you use.</p>

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

<p><a href="https://docs.python.org/2/library/xml.etree.elementtree.html" rel="nofollow">https://docs.python.org/2/library/xml.etree.elementtree.html</a></p>

<p><strong>Edit:</strong>  with the way that's structured, you can get a list of Data elements by saying</p>

<pre><code>for data in root.findall('Data'):
    item = data.find('Item') 
    print(item.tag ,":",item.text)
    value = data.find('Value') 
    print(value.tag ,":",value.text)
</code></pre>

<p>Now, understand that if that "Data" tag is not at the root level, then you need to root.find() until you can get to it.  In other words, if those "Data" tags are enclosed in some parent tags, you need to root.find("Parent Tag"), hope you get the gist of it</p>

<p><strong>Edit2:</strong>  Looked at my own msinfo.nfo file and this worked:</p>

<pre><code>disks = root.find(".//Category[@name='Disks']")

for disk in disks:
    item = disk.find('Item')
    print(item.tag ,":",item.text)
    value = disk.find('Value')
    print(value.tag ,":",value.text)
</code></pre>

<p>Note: This uses XPath syntax to find the element, which is only available in ElementTree1.3 (Python 2.7 and higher).  You can also brute force it by following the structure of the XML and traversing through the tree until you get to Disks.  The path was System Summary->Components->Storage->Disks and under Disks were those Data elements with Item and Value as children.</p>

python xml python-3.x tkinter