Вернуть только указанные c теги с elemtree - PullRequest
0 голосов
/ 31 января 2020

Я использую elementree для анализа файла XML с данными, взятыми с открытых карт, в новый (более короткий) файл. Я знаю, что данные содержатся в «узлах» и «тегах» с тегами, имеющими атрибуты. Некоторые узлы имеют тег с атрибутом addr: housenumber. Я могу прочитать из текущего файла и записать результаты в новый файл, используя iterparse со следующим кодом:

with open(OUTPUT_FILE, 'wb') as output:
for i, element in enumerate(get_elements(OSM_FILE)):
    output.write(ET.tostring(element, encoding='utf-8'))

Функция get_elements выглядит следующим образом:

def is_house_num(elem):
    return (elem.attrib['k'] == "addr:housenumber")

    for event, elem in context:
        if event == 'end' and elem.tag in tags:
            yield elem
            root.clear()

I Я могу определить, какие узлы имеют правильный тег атрибута, используя:

    for event, elem in context:
        if elem.tag == "node":
            for tag in elem.iter("tag"):
                if elem.attrib['k'] == "addr:housenumber":

Но когда я пытаюсь включить последний блок кода в свою функцию, я не могу сделать так, чтобы вывод в первом блок кода - это только узлы, которые содержат тег для атрибута addr: housenumber.

Пример файла, который я пытаюсь отфильтровать:

  <node id="356681982" lat="40.3980061" lon="-111.8418770" version="1" timestamp="2009-03-07T14:13:58Z" changeset="749606" uid="4732" user="iandees">
    <tag k="amenity" v="school"/>
    <tag k="ele" v="1397"/>
    <tag k="gnis:county_id" v="049"/>
    <tag k="gnis:created" v="02/25/1989"/>
    <tag k="gnis:feature_id" v="1448986"/>
    <tag k="gnis:state_id" v="49"/>
    <tag k="name" v="Sego Lily School"/>
  </node>
  <node id="356682074" lat="40.2799548" lon="-111.6457549" version="2" timestamp="2014-08-11T20:33:35Z" changeset="24687880" uid="2253787" user="1000hikes">
    <tag k="addr:city" v="Provo"/>
    <tag k="addr:housenumber" v="3570"/>
    <tag k="addr:postcode" v="84604"/>
    <tag k="addr:street" v="Timpview Drive"/>
    <tag k="building" v="school"/>
    <tag k="ele" v="1463"/>
    <tag k="gnis:county_id" v="049"/>
    <tag k="gnis:created" v="02/25/1989"/>
    <tag k="gnis:feature_id" v="1449106"/>
    <tag k="gnis:state_id" v="49"/>
    <tag k="name" v="Timpview High School"/>
    <tag k="operator" v="Provo School District"/>
  </node>
  <node id="356682151" lat="40.2221771" lon="-111.6590893" version="1" timestamp="2009-03-07T14:14:14Z" changeset="749606" uid="4732" user="iandees">
    <tag k="amenity" v="school"/>
    <tag k="ele" v="1376"/>
    <tag k="gnis:county_id" v="049"/>
    <tag k="gnis:created" v="02/25/1989"/>
    <tag k="gnis:feature_id" v="1449138"/>
    <tag k="gnis:state_id" v="49"/>
    <tag k="name" v="Utah Valley Vocational School"/>
  </node>

В этом случае я бы хотите, чтобы новый файл содержал только средний узел, например:

<node id="356682074" lat="40.2799548" lon="-111.6457549" version="2" timestamp="2014-08-11T20:33:35Z" changeset="24687880" uid="2253787" user="1000hikes">
    <tag k="addr:city" v="Provo"/>
    <tag k="addr:housenumber" v="3570"/>
    <tag k="addr:postcode" v="84604"/>
    <tag k="addr:street" v="Timpview Drive"/>
    <tag k="building" v="school"/>
    <tag k="ele" v="1463"/>
    <tag k="gnis:county_id" v="049"/>
    <tag k="gnis:created" v="02/25/1989"/>
    <tag k="gnis:feature_id" v="1449106"/>
    <tag k="gnis:state_id" v="49"/>
    <tag k="name" v="Timpview High School"/>
    <tag k="operator" v="Provo School District"/>
  </node>

1 Ответ

0 голосов
/ 31 января 2020

Спасибо, что указали мне в правильном направлении. Я смог заставить его работать, изменив мою функцию get_elements (которую, очевидно, я забыл включить выше), чтобы она выглядела так:

def get_elements(osm_file, tags = ('node', 'way')):
    context = iter(ET.iterparse(osm_file, events = ('start','end')))
    _, root = next(context)

    for event, elem in context:
        if elem.tag == "node" and event == 'end':
            for tag in elem.iter("tag"):
                if tag.attrib['k'] == "addr:housenumber":
                    yield elem
                    root.clear()
                else:
                    root.clear()
...