带有大文件的lxml:根据属性过滤出子树

问题描述 投票:0回答:1

我要解决的高级问题是我有一个1.5 GB的SMS数据转储,并且我试图过滤文件以仅保留与单个联系人之间的消息。

我正在Python中使用lxml来解析文件,但请告诉我是否有更好的选择。

XML文件的结构如下:

SMSES (root node)
  'count': 'xxxx',
  (Children):
      MMS
          'address': 'xxxx',
          'foo':     'bar',
           ... : ...,
           (Children)
               'other fields': 'that _do not_ specify address',
      MMS
          'address': 'xxxx',
          'foo':     'bar',
           ... : ...,
           (Children)
               'other fields': 'that _do not_ specify address'

即,我想遍历根节点的子节点,对于每个'地址'与特定值都不匹配的MMS,请删除该MMS及其所有后代(这些子节点倾向于保存图像等项)。 。

我尝试过的:

我发现了这样的问题/答案:how to remove an element in lxml

但是这些线程往往有没有嵌套元素的简单示例。

  • 我不清楚如何使用tree.xpath()查找匹配值的元素
  • 我尚不清楚是否调用remove(item)是否删除了该项目的后代(在这种情况下,我想删除它。)>
  • 我已经尝试了一种非常幼稚的方法,在该方法中,我获得了一个迭代器,然后遍历树,并随即删除了元素:

from lxml.etree import XMLParser, parse
p = XMLParser(huge_tree=True)
tree = parse('backup.xml', parser=p)

it = tree.iter()
item = next(it) # consume root node

for item in it:
    if item.attrib['address'] != '0000':
        item.getparent().remove(item)

此脚本的问题在于,迭代器执行DFS,并且MMS元素的子元素

具有地址字段。所以,我在寻找:
  • 完成任务的最有效+最简单的方法是什么?
  • 否则,如何强制tree.iter()仅在根的一级邻居上给我一个BFS迭代器?
  • remove(item)确实删除了所有后代,还是将子代附加到父代?
  • 感谢您抽出宝贵的时间阅读。很抱歉,如果这是一个幼稚的问题-解析XML文件并不是我的头等大事,并且LXML文档让我作为新手都很难阅读。

谢谢!

我要解决的高级问题是我有一个1.5 GB的SMS数据转储,并且我试图过滤文件以仅保留往返于单个联系人的消息。我在Python中使用lxml ...

python xml backup lxml large-files
1个回答
0
投票

[上周有一个新版本的Saxon / C具有Python语言绑定,并结合了XSLT 3.0流功能:这是一个非常新的软件,但您可以尝试一下(可从saxonica.com获得Saxon-EE评估许可证) 。样式表非常简单:

© www.soinside.com 2019 - 2024. All rights reserved.