我有一个XML文档,具有以下结构,我期待解析:
<base>
<intermediate>
<element>
<field1>some_text</field2>
<field2>more_text</field2>
</element>
# <element> repeated about 2000 times
</intermediate>
</base>
我的第一种方法是使用lxml的xslt接口将其转换为CSV,然后将此CSV读入python列表。
在表现不太像我所希望的那样之后,我想我会给予以下的尝试:
for intermediate in root.xpath('./intermediate'):
for element in index.xpath('./element[field2/text()]'):
field1 = element.xpath('field1/text()')[0]
field2 = element.xpath('field2/text()')[0]
结果是慢了很多。-这并不奇怪。
但是,我是否以最佳方式使用lxml呢?它的特性如此丰富,以至于我不能确定我没有为给定的问题选择一个糟糕的接口。
编辑1:基准测试结果
- 解决方案1:Python循环树遍历(如OP)- 77.9ms
- 解决方案2:交互解析- 11.4ms
- 解决方案3:XML解析和xslt(无csv解析)- 11.9ms
- 解决方案4:使用libxml 2在C中使用cython链接SAX解析器(在python中读取文件)- 2.33ms
用于xslt的代码:
xml = lxml.etree.parse('my_xml_file.xml')
xsl = lxml.etree.parse("my_xsl_file.xsl")
transformer = lxml.etree.XSLT(xsl)
result = transformer(xml)
csv_data = str(result)
使用的XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/base">
<xsl:text>field1|field2 </xsl:text>
<xsl:apply-templates select='intermediate/element[field2/text()]'/>
</xsl:template>
<xsl:template match="element">
<xsl:value-of select="field1"/><xsl:text>|</xsl:text>
<xsl:value-of select="field2"/><xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
3条答案
按热度按时间i2byvkas1#
下面的代码迭代地解析XML文件:
这里lxml以基于事件的方式工作,每次遇到end元素(
</xyz>
),就会生成一个end
事件,并由for
循环处理。变量
field1
和field2
会根据元素结束的位置进行设置,这里隐含的假设是<field1>
和<field2>
只出现在<element>
内部,并且不再嵌套。如果这些都得到了保证,那么当我们遇到一个结束的
</element>
时,这两个变量就包含了预期的字符串,如果这些不一定是真的,那么在迭代过程中就需要维护某种状态。在Python内部,这应该是最快的,因为它只依赖于在事件发生时解析事件,而根本不使用任何XPath。
3npbholx2#
您可以尝试
iterparse
:sr4lhrrt3#
这个答案是将备选方案4记录在@CPLTarun的OP中。
注意,这不是可生产的代码。这只是一个快速破解的基准测试。代码可能有bug。而且,它什至不能从python访问读取的数据,它只是把它保存在cython变量中,不断被覆盖。-这段代码并不打算有用,而是为完全充实的代码提供一个运行时的下限。
我可能从别人那里复制了这个代码的 backbone 。如果这个代码是你的,让我知道,我会相信你。
下面是jupyter笔记本上的代码,每个新单元格用
#%%
表示:注意:在清理之前,你可以在处理多个文件时只初始化解析器一次,这样可以保存时间。