【发布时间】:2023-03-04 08:22:02
【问题描述】:
我正在处理开放地图数据,需要能够根据它们的值更新特定标签。我已经能够读取标签,甚至将需要更新的特定标签打印到控制台,但我无法让它们更新。
我正在使用 elementree 和 lxml。我正在寻找的具体是如果 addr:street 标签的第一个词是基数方向(即北、南、东、西),而 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 和 lxml,因为 lxml 似乎是 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 North,并且 addr:street 标签应从 North 500 West 更改为 500 West。
【问题讨论】:
-
"我正在使用 elementree 和 lxml。"您是否在同一个程序中使用这两个库?
-
“我相信你在说什么”你在和谁说话? Stack Overflow 不是一个传统的讨论论坛。请确保提供minimal reproducible example。输入 XML 在哪里?
-
“lxml 似乎是 elementree 的一个子集”。反过来说:lxml 是 ElementTree 的超集。 lxml 支持与 ElementTree 相同的基本 API 以及许多附加功能。
-
很高兴知道,谢谢。我对解析 xml 非常陌生。
标签: python-3.x lxml elementtree large-files