lxml.etree iterparse()和完全解析元素

时间:2015-04-17 02:34:41

标签: python lxml elementtree iterparse

我有一个XML文件,其节点如下所示:

<trkpt lat="-37.7944415" lon="144.9616159">
  <ele>41.3681107</ele>
  <time>2015-04-11T03:52:33.000Z</time>
  <speed>3.9598</speed>
</trkpt>

我正在使用lxml.etree.iterparse()来迭代地解析树。我遍历每个trkpt元素的子元素,并希望打印子节点的文本值。 E.g。

for event, element in etree.iterparse(infile, events=("start", "end")):
    if element.tag == NAMESPACE + 'trkpt':
        for child in list(element):
            print child.text

问题是在此阶段节点没有文本,因此打印输出为“无”。

我通过用'print etree.tostring(child)'替换'print child.text'语句来验证这一点,输出看起来像这样

<ele/>
<time/>
<speed/>    

根据文档,“请注意,元素的文本,尾部和子元素在接收启动事件时不一定存在。只有结束事件才能保证元素已被完全解析。”

所以我将for循环更改为this,注意'if event ==“end”:'statement

for event, element in etree.iterparse(infile, events=("start", "end")):
    if element.tag == NAMESPACE + 'trkpt':
        if event == "end":
            for child in list(element):
                print child.text

但我仍然得到相同的结果。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

您是尝试显式使用iterparse还是使用其他方法?

e.g.

from lxml import etree

tree = etree.parse('/path/to/file')
root = tree.getroot()
for elements in root.findall('trkpt'):
    for child in elements:
        print child.text

lxml非常擅长解析而不占用太多内存......不确定这是否解决了您的问题,或者您是否尝试使用上述特定方法。

答案 1 :(得分:0)

你确定你不打电话,例如在您的条件声明之后element.clear(),像这样?

for event, element in etree.iterparse(infile, events=("start", "end")):
  if element.tag == NAMESPACE + 'trkpt' and event == 'end':
    for child in list(element):
        print child.text
  element.clear()

问题是解析器在为end发送trkpt事件之前发出子元素的事件(因为它首先遇到嵌套元素的结束标记)。如果在为外部元素调用end事件之前对已解析的元素进行任何修改,则可能会出现您描述的行为。

考虑以下备选方案:

for event, element in etree.iterparse(infile, events=('end',),
    tag=NAMESPACE + 'trkpt'):
  for child in element:
     print child.text
  element.clear()