我有一个超过1GB的xml文件,我想通过创建一个新的xml文件或重写现有的xml文件来删除父标记中不需要的子项来减小文件的大小。当文件很大时,如何通过python实现这一点,简单的解析tree = ElementTree.parse(xmlfile)
将不起作用。在
在每个父标记TasksReportNode
的文件中,我只希望具有值为0的TableRow
属性的子标记{
XML代码示例:
<TasksReportNode Name="Task15">
<TableData NumRows="97" NumColumns="15">
<TableRow RowCount="0">
<TableColumn Name="Task"><![CDATA[ Task15 [GET - /PULSEV31/appView/projectFeedHidden.jsp - 200]]]></TableColumn>
<TableColumn Name="Status"><![CDATA[Success]]></TableColumn>
<TableColumn Name="Successful"><![CDATA[96]]></TableColumn>
<TableColumn Name="Failed"><![CDATA[0]]></TableColumn>
<TableColumn Name="Timedout"><![CDATA[0]]></TableColumn>
<TableColumn Name="Total"><![CDATA[96]]></TableColumn>
<TableColumn Name="Min(ms)"><![CDATA[15]]></TableColumn>
<TableColumn Name="Avg(ms)"><![CDATA[24.20]]></TableColumn>
<TableColumn Name="Avg-90%(ms)"><![CDATA[54.55]]></TableColumn>
<TableColumn Name="90%ile(ms)"><![CDATA[89.98]]></TableColumn>
<TableColumn Name="95%ile(ms)"><![CDATA[95.24]]></TableColumn>
<TableColumn Name="99%ile(ms)"><![CDATA[99.45]]></TableColumn>
<TableColumn Name="Max(ms)"><![CDATA[94]]></TableColumn>
<TableColumn Name="Std. Dev."><![CDATA[15.74]]></TableColumn>
<TableColumn Name="Bytes Recd(KB)"><![CDATA[192]]></TableColumn>
</TableRow>
<TableRow RowCount="1">
<TableColumn Name="Task"><![CDATA[ VirtualUser1]]></TableColumn>
<TableColumn Name="Status"><![CDATA[Success]]></TableColumn>
<TableColumn Name="Successful"><![CDATA[1]]></TableColumn>
<TableColumn Name="Failed"><![CDATA[0]]></TableColumn>
<TableColumn Name="Timedout"><![CDATA[0]]></TableColumn>
<TableColumn Name="Total"><![CDATA[1]]></TableColumn>
<TableColumn Name="Min(ms)"><![CDATA[934]]></TableColumn>
<TableColumn Name="Avg(ms)"><![CDATA[934.00]]></TableColumn>
<TableColumn Name="Avg-90%(ms)"><![CDATA[950.00]]></TableColumn>
<TableColumn Name="90%ile(ms)"><![CDATA[1,000.50]]></TableColumn>
<TableColumn Name="95%ile(ms)"><![CDATA[1,000.50]]></TableColumn>
<TableColumn Name="99%ile(ms)"><![CDATA[1,000.50]]></TableColumn>
<TableColumn Name="Max(ms)"><![CDATA[934]]></TableColumn>
<TableColumn Name="Std. Dev."><![CDATA[0.00]]></TableColumn>
<TableColumn Name="Bytes Recd(KB)"><![CDATA[0]]></TableColumn>
</TableData>
<TableData NumRows="1" NumColumns="2">
<TableRow RowCount="0">
<TableColumn Name="Response Time Interval (ms)"><![CDATA[0 - 99]]></TableColumn>
<TableColumn Name="Frequency"><![CDATA[96]]></TableColumn>
</TableRow>
</TableData>
</TasksReportNode>
<TasksReportNode Name="Task16">
<TableData NumRows="97" NumColumns="15">
<TableRow RowCount="0">
<TableColumn Name="Task"><![CDATA[ Task16 [GET - /PULSEV31/appView/projectCommentHidden.jsp - 200]]]></TableColumn>
<TableColumn Name="Status"><![CDATA[Success]]></TableColumn>
<TableColumn Name="Successful"><![CDATA[96]]></TableColumn>
<TableColumn Name="Failed"><![CDATA[0]]></TableColumn>
<TableColumn Name="Timedout"><![CDATA[0]]></TableColumn>
<TableColumn Name="Total"><![CDATA[96]]></TableColumn>
<TableColumn Name="Min(ms)"><![CDATA[15]]></TableColumn>
<TableColumn Name="Avg(ms)"><![CDATA[22.73]]></TableColumn>
<TableColumn Name="Avg-90%(ms)"><![CDATA[54.55]]></TableColumn>
<TableColumn Name="90%ile(ms)"><![CDATA[90.93]]></TableColumn>
<TableColumn Name="95%ile(ms)"><![CDATA[96.25]]></TableColumn>
<TableColumn Name="99%ile(ms)"><![CDATA[100.50]]></TableColumn>
<TableColumn Name="Max(ms)"><![CDATA[109]]></TableColumn>
<TableColumn Name="Std. Dev."><![CDATA[14.76]]></TableColumn>
<TableColumn Name="Bytes Recd(KB)"><![CDATA[192]]></TableColumn>
</TableRow>
</TableData>
</TasksReportNode>
以下是我尝试过的:
^{pr2}$现在我们有了所有值为“0”的RowCount
,这些值可以添加到parent中,剩下所有其他同级。在
我建议使用
lxml
,因为它在大多数方面比stdlibxml.ElementTree
更有效。在不要试图将整个文档作为一个整体来解析,因为它太大了,而应该迭代地处理源文档。在
在
lxml
页是Event driven parsing有两种选择:
etree.iterparse
我个人更喜欢
etree.iterparse
,因为它以更方便的方式为您解析了元素。但是您不能忘记对处理过的部分执行清理工作,否则与一次解析整个文档相比,您不会节省任何内存。在编辑:添加真实示例
例子比大量的理论更能说明问题。以下是我的尝试:
为了测试性能,我取了你的大样本文件(73MB),重复内部部分10次,得到 773 MB的大型XML文件,并已处理该文件。在
处理耗时24秒(ZenbookCoreI7,内存为4GB),结果文件的大小为4.7MB。在
举例说明
默认情况下,
iterparse
只提供“end”事件,当某个元素被完全解析时激发。在这个解决方案使用了这样一个事实,即即使使用
iterparse
,元素也会保存在内存中。这是用过的 在以下位置:element.clear()
)并被删除 (element.remove(rowelm)
)。clear()
清除元素的内部内容,但是元素 仍然存在。remove()
对父元素起作用,并从中删除内部部分。在element
是根目录。它还在记忆中, 所以我可以把它作为字符串写入文件。在在
remove()
元素时必须小心。正在尝试从位于的父级中删除元素 当前迭代元素的瞬间导致分割错误。因此,代码 使用"TableRow"
元素remove()
等待,直到完成对父元素TableData
的解析。在变量
toremove
用于收集所有"TableRow"
元素,并在父元素后立即使用"TableData"
元素被完全解析。注意,remove()
只对实际元素有效 父母,所以我们一定要在适当的时候做。在更大文件的想法
对于更大的文件,此解决方案将受到结果XML文档大小的限制 保存在内存中,直到源XML的修剪完成。在
对于这样的场景,我们必须在解析过程中写出输出,并将 内存中已处理的所有元素。实际上,你必须写下 “开始”事件时的“打开XML元素”部分(如
"<TaskReportSummary att="a" otheratt="bb"
) 将出现,并在“end”事件中编写关闭XML元素部分"/>"
。在以下是我尝试过的:
现在我们有了值为“0”的所有行数,可以将其添加到parent中,剩下所有其他同级。在
相关问题 更多 >
编程相关推荐