我要解决的高级问题是我有一个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迭代器? 感谢您抽出宝贵的时间阅读。抱歉,如果这是一个幼稚的问题-解析XML文件并不是我的头等大事,而LXML文档对于我来说是一个新手,很难理解。
谢谢!
答案 0 :(得分:0)
上周有一个新版本的Saxon / C具有Python语言绑定功能,并结合了XSLT 3.0流功能:这是一个非常新的软件,但您可以尝试一下(使用可从saxonica.com获得的Saxon-EE评估许可证。 )。样式表非常简单:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode streamable="yes"/>
<xsl:template match="/">
<SMSES>
<xsl:copy-of select="SMS[@address='specific value']"/>
</SMSES>
</xsl:template>
</xsl:transform>
不幸的是,您已经抽象了XML,所以我无法确定“ address”实际上是元素还是属性,并且在流式传输时有很大的不同。我在这里假设它是一个属性,但是如果您提供真实的XML示例,那么我可以帮助您产生一些真实的XSLT代码。
如果没有真正的必须从Python运行的约束,您也可以使用已建立的Saxon / Java产品直接从命令行运行它。但无论哪种方式,流媒体都需要Saxon企业版。