Я работаю с открытыми данными карты и должен иметь возможность обновлять определенные c теги на основе их значений. Мне удалось прочитать теги и даже напечатать указанные теги c, которые необходимо обновить на консоли, но я не смог их обновить.
Я использую elementree и l xml. Что мне особенно нужно, так это если первое слово тега addr: street является направлением мощности (ie Север, Юг, Восток, Запад), а последнее слово тега addr: housenumber НЕ является направлением мощности, возьмите первое слово из тега addr: street и переместите его, чтобы оно стало последним словом тега addr: housenumber.
Отредактировано на основе приведенных ниже вопросов.
Сначала я просто вызывал код с:
clean_data(OUTPUT_FILE)
Я не осознавал, что iterparse нельзя использовать для прямой печати из метода (который, как я полагаю, является тем, что вы говорите). У меня был код из другой части проекта, который я использовал ранее, поэтому я адаптировал то, что вы написали, что у меня было раньше Вот что у меня есть:
Ранее в файле:
import xml.etree.cElementTree as ET
from collections import defaultdict
import pprint
import re
import codecs
import json
OSM_FILE = "Utah County Map.osm"
OUTPUT_FILE = "Utah County Extract.osm"
JSON_FILE = "JSON MAP DATA.json"
код в этом разделе проекта:
def clean_data(osm_file, tags = ('node', 'way')):
context = iter(ET.iterparse(osm_file, events=('end',)))
for event, elem in context:
if elem.tag == 'node':
streetTag, street = getVal(elem, 'addr:street')
if street is None: # No "street"
continue
first_word = getWord(street, True)
houseTag, houseNo = getVal(elem, 'addr:housenumber')
if houseNo is None: # No "housenumber"
continue
last_word = getWord(houseNo, False)
if first_word in direct_list and last_word not in direct_list:
streetTag.attrib['v'] = street[len(first_word) + 1:]
houseTag.attrib['v'] = houseNo + ' ' + first_word
for i, element in enumerate(clean_data(OUTPUT_FILE)):
print(ET.tostring(context.root, encoding='unicode', pretty_print=True, with_tail=False))
Когда я запускаю это прямо сейчас, я получаю сообщение об ошибке:
TypeError: 'NoneType' object is not iterable
Я попытался добавить в выходной код, который использовал ранее для другого раздела проекта, но получил ту же ошибку. Вот этот код для справки. (Выходной файл в этом коде относится к выходным данным первого этапа очистки данных, где я удалил несколько недопустимых узлов).
with open(CLEAN_DATA, 'w') as output:
output.write('<?xml version="1.0" encoding="UTF-8"?>\n')
output.write('<osm>\n ')
for i, element in enumerate(clean_data(OUTPUT_FILE)):
output.write(ET.tostring(element, encoding='unicode'))
output.write('</osm>')
Первоначальное редактирование было в ответ на вопрос Valdi_bo ниже. Вот пример из моего файла xml для справки. Да, я использую и Elementree, и l xml, поскольку l xml кажется подмножеством elementree. Некоторые функции, которые я вызывал ранее в программе, работали только с одной или другой, поэтому я использую оба.
<?xml version="1.0" encoding="UTF-8"?>
<osm>
<node changeset="24687880" id="356682074" lat="40.2799548" lon="-111.6457549" timestamp="2014-08-11T20:33:35Z" uid="2253787" user="1000hikes" version="2">
<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 changeset="58421729" id="356685655" lat="40.2414325" lon="-111.6678877" timestamp="2018-04-25T20:23:33Z" uid="360392" user="maxerickson" version="4">
<tag k="addr:city" v="Provo" />
<tag k="addr:housenumber" v="585" />
<tag k="addr:postcode" v="84601" />
<tag k="addr:street" v="North 500 West" />
<tag k="amenity" v="doctors" />
<tag k="gnis:feature_id" v="2432255" />
<tag k="healthcare" v="doctor" />
<tag k="healthcare:speciality" v="gynecology;obstetrics" />
<tag k="name" v="Valley Obstetrics & Gynecology" />
<tag k="old_name" v="Healthsouth Provo Surgical Center" />
<tag k="phone" v="+1 801 374 1801" />
<tag k="website" v="http://valleyobgynutah.com/location/provo-office-2/" />
</node>
</osm>
В этом примере первый узел останется изменилось. Во втором блоке тег addr: housenumber должен быть изменен с 585 на 585 северной широты, а тег addr: street - с северной части 500 западных на 500 западных.