0

我是 xml 和 python 的新手,我希望我能正确表达我的问题:

我有大小为 1 GB 的 xml 文件。文件如下所示:

<test name="LongTestname" result="PASS">
    <step ID="0" step="NameOfStep1" result="PASS">
        Stuff I dont't care about
    </step>
    <step ID="1" step="NameOfStep2" result="PASS">
        Stuff I dont't care about
    </step>
</test>

为了快速分析,我想获取作为根元素子元素的步骤的名称和结果。我不关心的是很多嵌套元素。

我已经尝试过以下操作:

tree = ET.parse(xmlLocation)
root = tree.getroot()
for child in root:
    print(child.tag, child.attrib)

在这里我得到一个内存错误,因为文件太大了

然后我尝试了:

try:
    for event, elem in ET.iterparse(pathToSteps, events=("start","end")):
       if elem.tag == "step" and event == "start":
                        
           stepAndResult.append([elem.attrib['step'],elem.attrib['result'],"System1"])
       elem.clear()

这有效,但真的很慢。我猜它会遍历所有元素,这需要很长时间。

然后我找到了一个看起来像这样的解决方案:

try:
    tree = ET.iterparse(pathToSteps, events=("start","end"))
    _, root = next(tree)  
    print('ROOT:', root.tag)
except:
   print("ERROR: Unable to open and parse file !!!")


for child in root:
   print(child.attrib)

但这仅打印第一步的属性。

有没有办法加快工作解决方案?由于我对这些东西很陌生,我希望有一个完整的示例或参考,我可以通过一个示例自己弄清楚。

4

2 回答 2

0

我认为你在正确的轨道上iterparse()

也许尝试step在参数中指定元素名称tag并只处理“开始”事件......

from lxml import etree

for event, elem in etree.iterparse("input.xml", tag="step", events=("start",)):
    print(elem.attrib)
    elem.clear()

编辑:出于某种原因,我认为您使用的是 lxml 而不是 ElementTree。我的回答将要求您切换到 lxml。

于 2021-07-22T14:47:46.910 回答
0

在不了解您的设置细节的情况下,可能很难猜测“最快”可能是什么以及由于文件解析导致的延迟有多少。我要做的第一件事当然是运行时间,这样你就有了一些初始基准。然后我会编写一个简单的 python 程序,除了从磁盘读取文件(没有 XML 解析)之外什么都不做。如果时间差不显着,那么 XML 解析不是问题,而是从磁盘读取文件是问题。当然,在 XML 文档中,文件本身没有指示下一个标签在哪里结束,因此不可能跳过与这些部分关联的 IO(您仍然需要对文件进行线性读取)。除了可能使用不同的编程语言(未解释)之外,

如果您确实从实际的 XML 解析中获得了显着的减慢,那么您可能会尝试将文件预处理为不同的文件。由于文件的文件格式是非常静态的,您可以读取文件并输出到不同的文件(使用正则表达式),直到获得标签。然后只需丢弃数据,直到您关闭</step>标签或</test>标签。这将产生一个有效但希望小得多的 XML 文件。这里的关键是自己进行“解析”,而不是让底层解析器尝试理解所有文档格式,因为您的格式很简单,这可能会快得多。然后你可以在这个输出上运行你的原始程序,它不会“看到”任何无关的标签。当然,如果你真的嵌套了,这会中断<step>标签,但如果是这种情况,那么您可能需要使用真正的 XML 解析器来解析文件,以了解第一级的开始和停止位置。

于 2021-07-22T13:30:46.423 回答