为什么iterparse会跳过这个OpenStreetMap树的某些元素?

时间:2015-04-17 21:27:46

标签: python xml openstreetmap iterparse

我有一个OSM文件,可以捕获一个小邻居。 http://pastebin.com/xeWJsPeY

我有Python代码可以进行大量额外的解析,但是主要问题的一个例子可以在这里看到:

import xml.etree.cElementTree as CET
osmfile = open('osm_example.osm','r')
for event, elem in CET.iterparse(osmfile,events = ('start',)):
    if elem.tag == 'way':
        if elem.get('id') == "21850789":
            for child in elem:
                print CET.tostring(child,encoding='utf-8')
    elem.clear()

在这里和其他地方,我注意到缺少特定条目的标签(其中标签是一个看起来像<tag k="highway" v="residential" />的元素。所有<nd .../>个元素都被正确读取,我可以看到。

我在处理文件时注意到的另一件事是,当我对带有tostring()标记的元素使用'way'时,如果有<tag .../>个元素被读取错误,那么没有在换行结尾添加换行符。例如,在跑步时

for event, elem in CET.iterparse(osmfile,events = ('start',)):
    if elem.tag == 'way':
        print CET.tostring(elem,encoding='utf-8')
    elem.clear()

缺少<tag .../>元素的条目的输出是

<nd ref="235476200" />
  <nd ref="1865868598" /></way><way changeset="12727901" id="21853023" timestamp="2012-08-14T15:23:13Z" uid="451048" user="bbmiller" version="8" visible="true">
  <nd ref="1865868557" />

与一个形成得很好的人相比,

 <tag k="tiger:zip_left" v="60061" />
  <tag k="tiger:zip_right" v="60061" />
 </way>
 <way changeset="15851022" id="21874389" timestamp="2013-04-24T16:33:28Z" uid="451693" user="bot-mode" version="3" visible="true">
  <nd ref="235666887" />
  <nd ref="235666891" />

这里发生的问题是什么?

1 个答案:

答案 0 :(得分:1)

您似乎在搜索子元素以响应start事件。但是孩子们的元素还没有被阅读过。

考虑这个片段:

<a>foo<b/></a>

start事件发生在解析器读取<a>之后,但在读取foo之前,以及在读取<b/>之前更多的事件。正如the documentation所说:

  
    

注意iterparse()仅保证在发出“start”事件时看到了起始标记的“&gt;”字符,因此定义了属性,但text和tail属性的内容未定义那一点。这同样适用于儿童元素;他们可能会或可能不会在场。

         

如果您需要完全填充的元素,请改为寻找“结束”事件。

  

因此,您可以使用此代码获得所需的行为:

for event, elem in CET.iterparse(osmfile,events = ('end',)):