【问题标题】:Python Parse XML file for certain lines and output the line to Text widgetPython 为某些行解析 XML 文件并将该行输出到 Text 小部件
【发布时间】:2016-08-30 18:56:16
【问题描述】:

我需要在 Windows msinfo 文件 (.nfo) 中搜索某些行并将它们打印到文本小部件。我可以print(line) 文件中的任何一行,并且可以将每一行输出到 Text 小部件,但是一旦我尝试指定要输出的行,它就会停止工作。我认为这是因为该文件是 XML,但我为 python 看到的 XML 解析工具似乎在寻找像 data=blah 这样的行。当我在 txt 编辑器中打开它们时,我正在寻找的条目如下所示:

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

我发现post 询问我想要什么,但解决方案不起作用。未找到 ET.parse:

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)

当使用上面我得到这个:

"C:\Program Files (x86)\Python35-32\python.exe" "D:/MY STUFF/Programming/Python/testing.py" Traceback(最近调用 最后):文件“D:/MY STUFF/Programming/Python/testing.py”,第 3 行,在 tree = ET.parse(file) AttributeError: module 'xml.etree' has no attribute 'parse'

进程以退出代码 1 结束

这是我的代码中的一个 sn-p:

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")

如果我删除 if "Model" in line:,那么它会将所有内容都转储到 Text 小部件中。

这是它们在 Windows 上正常打开时的外观:

关于如何从 nfo/XML 文件中提取我需要的行有什么建议吗?

此外,当从 xml 打印行时,字体更大且间距为双倍。如何使该行以与普通 txt 文件相同的方式打印?

【问题讨论】:

  • 你应该可以使用 ElementTree... 你能详细说明你在尝试使用 ET.parse 解析它时使用的代码吗?
  • @d_rez90 我在原帖中添加了示例
  • 检查我的更新答案
  • 你得到的错误是因为你导入了错误的东西。你需要做 import xml.etree.ElementTree as ET
  • @d_rez90 哎呀。好的,导入已修复,不再出现解析错误。现在我需要弄清楚如何将解析器指向磁盘类别,以便获得正确的项目和值。

标签: python xml python-3.x tkinter


【解决方案1】:

所以您需要了解 XML 的结构,然后使用您要查找的实际标签而不是“数据”

    item = element.find('Item') 
    print(item.tag ,":",item.text)
    value = element.find('Value') 
    print(value.tag ,":",value.text)

您的实际问题是您需要更改您使用的导入。

import xml.etree.ElementTree as ET

https://docs.python.org/2/library/xml.etree.elementtree.html

编辑:使用结构化的方式,您可以通过以下方式获取数据元素列表

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

现在,了解如果“数据”标签不在根级别,那么您需要 root.find() 直到可以访问它。换句话说,如果那些“Data”标签包含在一些父标签中,你需要root.find(“Parent Tag”),希望你明白它的要点

Edit2:查看了我自己的 msinfo.nfo 文件,这很有效:

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)

注意:这使用 XPath 语法来查找元素,这仅在 ElementTree1.3(Python 2.7 和更高版本)中可用。您还可以通过遵循 XML 的结构并遍历树直到到达磁盘来强制它。路径是 System Summary->Components->Storage->Disks,在 Disks 下是那些以 Item 和 Value 作为子项的数据元素。

【讨论】:

  • 直到 10 分钟前我才看到您的 Edit2。我能够使用它来找到我需要的一切并输出到我的文本小部件。感谢您花费额外的时间帮助我了解它的工作原理。
【解决方案2】:

这是我的代码与您的示例数据,我知道它可以写得更好,但我认为这可以解决您的问题 :)
你必须找到根(xml)然后迭代它的文本!您还可以使用其他方法,例如iterfind 以获得更好的解决方案

xml_file  = "<xml><Item><![CDATA[Model]]></Item><Value><![CDATA[TOSHIB  MK1652GSX SCSI Disk Device]]></Value></xml>"
from xml.etree import ElementTree
root = ElementTree.fromstring(xml_file)

start = root.itertext()

while True:
    try:
        print start.next()
    except StopIteration:
        break

这是输出:

>>>Model
>>>TOSHIB  MK1652GSX SCSI Disk Device

【讨论】:

    猜你喜欢
    • 2023-03-05
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多