Skip to content

Commit a7ecfd0

Browse files
committed
V58
- Nevenadressen are now parsed. They are stored in a nevenadressen table. - Adressen table has a new hoofd_nummer_id field. If filled, points to the hoofdadres. - Parser now handles multiple field values. For example, a verblijfsobject can contain multiple nevenadressen. - Updated progress bar data - Renamed "openbareruimte_id" field in nummers table to "openbare_ruimte_id" - More logging when creating adressen table.
1 parent dffa731 commit a7ecfd0

File tree

5 files changed

+155
-76
lines changed

5 files changed

+155
-76
lines changed

bag/bag_parser.py

+24-19
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def parse(self, tag_name):
4646

4747
self.object_tag_name = ns_objecten + tag_name
4848
self.file_bag_code = "9999WPL"
49-
self.total_xml = 3889 # required for progress indicator. Actual numbers can be found in the console or log.
49+
self.total_xml = 4049 # required for progress indicator. Actual numbers can be found in the console or log.
5050
self.data_init = {'geometry': ''}
5151
self.save_to_database = self.__save_woonplaats
5252
self.db_fields = {
@@ -65,7 +65,7 @@ def parse(self, tag_name):
6565

6666
self.object_tag_name = ns_gwr_product + tag_name
6767
self.file_bag_code = "GEM-WPL-RELATIE"
68-
self.total_xml = 5765 # required for progress indicator
68+
self.total_xml = 5773 # required for progress indicator
6969
self.save_to_database = self.__save_gemeente_woonplaats
7070

7171
self.db_fields = {
@@ -86,9 +86,9 @@ def parse(self, tag_name):
8686

8787
self.object_tag_name = ns_objecten + tag_name
8888
self.file_bag_code = "9999OPR"
89-
self.total_xml = 343448 # required for progress indicator
89+
self.total_xml = 346970 # required for progress indicator
9090
self.data_init = {'verkorte_naam': ''}
91-
self.save_to_database = self.__save_openbareruimte
91+
self.save_to_database = self.__save_openbare_ruimte
9292

9393
self.db_fields = {
9494
ns_objecten + 'identificatie': 'id',
@@ -109,7 +109,7 @@ def parse(self, tag_name):
109109

110110
self.object_tag_name = ns_objecten + tag_name
111111
self.file_bag_code = "9999NUM"
112-
self.total_xml = 12054045 # required for progress indicator
112+
self.total_xml = 12287165 # required for progress indicator
113113
# Initialization required as BAG leaves fields out of the data if it is empty
114114
self.data_init = {'huisletter': '', 'toevoeging': '', 'postcode': '', 'woonplaats_id': ''}
115115
self.save_to_database = self.__save_nummer
@@ -123,7 +123,7 @@ def parse(self, tag_name):
123123
ns_historie + 'beginGeldigheid': 'begindatum_geldigheid',
124124
ns_historie + 'eindGeldigheid': 'einddatum_geldigheid',
125125
ns_objecten + 'status': 'status',
126-
ns_objecten_ref + 'OpenbareRuimteRef': 'openbareruimte_id',
126+
ns_objecten_ref + 'OpenbareRuimteRef': 'openbare_ruimte_id',
127127
ns_objecten_ref + 'WoonplaatsRef': 'woonplaats_id',
128128
}
129129
self.db_tag_parent_fields = {}
@@ -134,7 +134,7 @@ def parse(self, tag_name):
134134

135135
self.object_tag_name = ns_objecten + tag_name
136136
self.file_bag_code = "9999PND"
137-
self.total_xml = 20352252 # required for progress indicator
137+
self.total_xml = 21286109 # required for progress indicator
138138
self.data_init = {'geometry': ''}
139139
self.save_to_database = self.__save_pand
140140

@@ -157,8 +157,8 @@ def parse(self, tag_name):
157157

158158
self.object_tag_name = ns_objecten + tag_name
159159
self.file_bag_code = "9999VBO"
160-
self.total_xml = 21148447 # required for progress indicator
161-
self.data_init = {'pos': '', 'rd_x': '', 'rd_y': '', 'latitude': '', 'longitude': ''}
160+
self.total_xml = 22552963 # required for progress indicator
161+
self.data_init = {'pos': '', 'rd_x': '', 'rd_y': '', 'latitude': '', 'longitude': '', 'nevenadressen': ''}
162162
self.save_to_database = self.__save_verblijfsobject
163163

164164
self.db_fields = {
@@ -175,6 +175,7 @@ def parse(self, tag_name):
175175
# Therefore, identification is done by combining the tag with the parent tag
176176
self.db_tag_parent_fields = {
177177
ns_objecten + 'heeftAlsHoofdadres' + ns_objecten_ref + 'NummeraanduidingRef': 'nummer_id',
178+
ns_objecten + 'heeftAlsNevenadres' + ns_objecten_ref + 'NummeraanduidingRef': 'nevenadressen',
178179
}
179180
elif self.tag_name == 'Ligplaats':
180181
ns_objecten = "{www.kadaster.nl/schemas/lvbag/imbag/objecten/v20200601}"
@@ -184,7 +185,7 @@ def parse(self, tag_name):
184185

185186
self.object_tag_name = ns_objecten + tag_name
186187
self.file_bag_code = "9999LIG"
187-
self.total_xml = 17653 # required for progress indicator
188+
self.total_xml = 18131 # required for progress indicator
188189
self.data_init = {'pos': '', 'rd_x': '', 'rd_y': '', 'latitude': '', 'longitude': '', 'geometry': ''}
189190
self.save_to_database = self.__save_ligplaats
190191

@@ -210,7 +211,7 @@ def parse(self, tag_name):
210211

211212
self.object_tag_name = ns_objecten + tag_name
212213
self.file_bag_code = "9999STA"
213-
self.total_xml = 49543 # required for progress indicator
214+
self.total_xml = 56684 # required for progress indicator
214215
self.data_init = {'pos': '', 'rd_x': '', 'rd_y': '', 'latitude': '', 'longitude': '', 'geometry': ''}
215216
self.save_to_database = self.__save_standplaats
216217

@@ -279,13 +280,14 @@ def __update_status(self, final=False):
279280

280281
def __parse_file(self, file_xml):
281282
data = self.data_init.copy()
282-
tag_previous = None
283-
tag_now = None
283+
parent_tags = []
284+
284285
for event, elem in ElementTree.iterparse(file_xml, events=("start", "end")):
285286
if event == 'start':
286-
tag_previous = tag_now
287-
tag_now = elem.tag
287+
parent_tags.append(elem.tag)
288288
elif event == 'end':
289+
parent_tags.pop()
290+
289291
# Note: elem.text is only guaranteed in 'end' event
290292
if elem.tag == self.object_tag_name:
291293
self.count_xml += 1
@@ -295,11 +297,14 @@ def __parse_file(self, file_xml):
295297
else:
296298
field_found = False
297299

298-
if self.db_tag_parent_fields and tag_previous:
299-
parent_elem_tag = tag_previous + elem.tag
300+
if self.db_tag_parent_fields and parent_tags:
301+
parent_elem_tag = parent_tags[-1] + elem.tag
300302
field_parent_elem = self.db_tag_parent_fields.get(parent_elem_tag)
301303
if field_parent_elem:
302-
data[field_parent_elem] = elem.text
304+
if field_parent_elem in data and data[field_parent_elem]:
305+
data[field_parent_elem] += "," + elem.text
306+
else:
307+
data[field_parent_elem] = elem.text
303308
field_found = True
304309

305310
if not field_found:
@@ -322,7 +327,7 @@ def __save_gemeente_woonplaats(self, data):
322327
self.__update_status()
323328
self.database.save_gemeente_woonplaats(data)
324329

325-
def __save_openbareruimte(self, data):
330+
def __save_openbare_ruimte(self, data):
326331
if (self.__bag_einddatum_valid(data) and
327332
self.__bag_begindatum_valid(data) and
328333
data['status'] == "Naamgeving uitgegeven"):

config.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import locale
22

3-
version = 56
4-
version_date = '20 June 2023'
3+
version = 58
4+
version_date = '4 July 2023'
55

66
locale.setlocale(locale.LC_ALL, 'nl_NL')
77

@@ -23,7 +23,7 @@
2323

2424
# If an adressen table is created some BAG tables are no longer needed and can be deleted:
2525
# nummers, panden, verblijfsobjecten, ligplaatsen and standplaatsen. Set to False if you want to keep these tables.
26-
# You can also delete these tables afterwards using the utils_sqlite_shrink.py script.
26+
# You can also delete these tables afterward using the utils_sqlite_shrink.py script.
2727
delete_no_longer_needed_bag_tables = True
2828

2929
# Public spaces with names longer than 24 characters also have a shortened name. Set to true to make short names the

database_sqlite/database_sqlite.py

+98-35
Original file line numberDiff line numberDiff line change
@@ -71,32 +71,40 @@ def save_openbare_ruimte(self, data):
7171
def save_nummer(self, data):
7272
# Note: Use replace, because BAG does not always contain unique id's
7373
self.connection.execute(
74-
"""REPLACE INTO nummers (id, postcode, huisnummer, huisletter, toevoeging, woonplaats_id, openbareruimte_id,
75-
status) VALUES(?, ?, ?, ?, ?, ?, ?, ?);
74+
"""REPLACE INTO nummers (id, postcode, huisnummer, huisletter, toevoeging, woonplaats_id,
75+
openbare_ruimte_id, status) VALUES(?, ?, ?, ?, ?, ?, ?, ?);
7676
""",
7777
(data["id"], data["postcode"], data["huisnummer"], data["huisletter"], data["toevoeging"],
78-
data["woonplaats_id"], data["openbareruimte_id"], data["status"])
78+
data["woonplaats_id"], data["openbare_ruimte_id"], data["status"])
7979
)
8080

81-
8281
def save_pand(self, data):
8382
# Note: Use replace, because BAG does not always contain unique id's
8483
self.connection.execute(
8584
"""REPLACE INTO panden (id, bouwjaar, status, geometry)
8685
VALUES(?, ?, ?, ?)
8786
""",
88-
(data["id"], data["bouwjaar"], data["status"], data["geometry"]))
87+
(data["id"], data["bouwjaar"], data["status"], data["geometry"])
88+
)
8989

9090
def save_verblijfsobject(self, data):
9191
# Note: Use replace, because BAG does not always contain unique id's
9292
self.connection.execute(
9393
"""REPLACE INTO verblijfsobjecten (id, nummer_id, pand_id, oppervlakte, rd_x, rd_y, latitude, longitude,
94-
gebruiksdoel, status) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
94+
gebruiksdoel, status) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
9595
""",
9696
(data["id"], data["nummer_id"], data["pand_id"], data["oppervlakte"], data["rd_x"], data["rd_y"],
9797
data["latitude"], data["longitude"], data["gebruiksdoel"], data["status"])
9898
)
9999

100+
if data["nevenadressen"]:
101+
nevenadressen = data["nevenadressen"].split(",")
102+
for neven_nummer_id in nevenadressen:
103+
self.connection.execute("""
104+
INSERT INTO nevenadressen (verblijfsobject_id, neven_nummer_id, hoofd_nummer_id) VALUES (?, ?, ?);
105+
""", (data["id"], neven_nummer_id, data["nummer_id"])
106+
)
107+
100108
def save_ligplaats(self, data):
101109
# Note: Use replace, because BAG does not always contain unique id's
102110
self.connection.execute(
@@ -130,27 +138,35 @@ def create_bag_tables(self):
130138
131139
DROP TABLE IF EXISTS openbare_ruimten;
132140
CREATE TABLE openbare_ruimten (id INTEGER PRIMARY KEY, naam TEXT, lange_naam TEXT, verkorte_naam TEXT,
133-
type TEXT, woonplaats_id INTEGER);
141+
type TEXT, woonplaats_id INTEGER);
134142
135143
DROP TABLE IF EXISTS nummers;
136144
CREATE TABLE nummers (id TEXT PRIMARY KEY, postcode TEXT, huisnummer INTEGER, huisletter TEXT,
137-
toevoeging TEXT, woonplaats_id TEXT, openbareruimte_id TEXT, status TEXT);
145+
toevoeging TEXT, woonplaats_id TEXT, openbare_ruimte_id TEXT, status TEXT);
138146
139147
DROP TABLE IF EXISTS panden;
140148
CREATE TABLE panden (id TEXT PRIMARY KEY, bouwjaar INTEGER, status TEXT, geometry TEXT);
141149
142150
DROP TABLE IF EXISTS verblijfsobjecten;
143151
CREATE TABLE verblijfsobjecten (id TEXT PRIMARY KEY, nummer_id TEXT, pand_id TEXT,
144-
oppervlakte FLOAT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT, longitude FLOAT, gebruiksdoel TEXT,
145-
status TEXT);
152+
oppervlakte FLOAT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT, longitude FLOAT, gebruiksdoel TEXT,
153+
status TEXT);
154+
155+
DROP TABLE IF EXISTS nevenadressen;
156+
CREATE TABLE nevenadressen (
157+
verblijfsobject_id TEXT,
158+
neven_nummer_id TEXT,
159+
hoofd_nummer_id TEXT,
160+
PRIMARY KEY (verblijfsobject_id, neven_nummer_id)
161+
);
146162
147163
DROP TABLE IF EXISTS ligplaatsen;
148164
CREATE TABLE ligplaatsen (id TEXT PRIMARY KEY, nummer_id TEXT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT,
149-
longitude FLOAT, status TEXT, geometry TEXT);
165+
longitude FLOAT, status TEXT, geometry TEXT);
150166
151167
DROP TABLE IF EXISTS standplaatsen;
152168
CREATE TABLE standplaatsen (id TEXT PRIMARY KEY, nummer_id TEXT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT,
153-
longitude FLOAT, status TEXT, geometry TEXT);
169+
longitude FLOAT, status TEXT, geometry TEXT);
154170
""")
155171
self.connection.commit()
156172

@@ -173,48 +189,60 @@ def create_indices_adressen(self):
173189

174190
def create_adressen_from_bag(self):
175191

192+
utils.print_log('create adressen tabel: import adressen')
176193
self.connection.executescript(f"""
177194
DROP TABLE IF EXISTS adressen;
178195
179196
CREATE TABLE adressen (nummer_id TEXT PRIMARY KEY, pand_id TEXT, verblijfsobject_id TEXT,
180197
gemeente_id INTEGER, woonplaats_id INTEGER, openbare_ruimte_id INTEGER, object_type TEXT,
181198
gebruiksdoel TEXT, postcode TEXT, huisnummer INTEGER, huisletter TEXT, toevoeging TEXT,
182-
oppervlakte FLOAT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT, longitude FLOAT, bouwjaar INTEGER,
199+
oppervlakte FLOAT, rd_x FLOAT, rd_y FLOAT, latitude FLOAT, longitude FLOAT, bouwjaar INTEGER,
200+
hoofd_nummer_id TEXT,
183201
geometry TEXT);
184202
185203
INSERT INTO adressen (nummer_id, pand_id, verblijfsobject_id, gemeente_id, woonplaats_id,
186204
openbare_ruimte_id, object_type, gebruiksdoel, postcode, huisnummer, huisletter, toevoeging,
187205
oppervlakte, rd_x, rd_y, longitude, latitude, bouwjaar, geometry)
188206
SELECT
189-
n.id AS nummer_id,
190-
p.id AS pand_id,
191-
v.id AS verblijfsobject_id,
192-
w.gemeente_id,
193-
o.woonplaats_id,
194-
o.id,
195-
'verblijfsobject',
196-
v.gebruiksdoel,
197-
n.postcode,
198-
n.huisnummer,
199-
n.huisletter,
200-
n.toevoeging,
201-
v.oppervlakte,
202-
v.rd_x,
203-
v.rd_y,
204-
v.longitude,
205-
v.latitude,
206-
p.bouwjaar,
207-
p.geometry
207+
n.id AS nummer_id,
208+
p.id AS pand_id,
209+
v.id AS verblijfsobject_id,
210+
w.gemeente_id,
211+
o.woonplaats_id,
212+
o.id,
213+
'verblijfsobject',
214+
v.gebruiksdoel,
215+
n.postcode,
216+
n.huisnummer,
217+
n.huisletter,
218+
n.toevoeging,
219+
v.oppervlakte,
220+
v.rd_x,
221+
v.rd_y,
222+
v.longitude,
223+
v.latitude,
224+
p.bouwjaar,
225+
p.geometry
208226
FROM nummers n
209-
LEFT JOIN openbare_ruimten o ON o.id = n.openbareruimte_id
227+
LEFT JOIN openbare_ruimten o ON o.id = n.openbare_ruimte_id
210228
LEFT JOIN woonplaatsen w ON w.id = o.woonplaats_id
211229
LEFT JOIN verblijfsobjecten v ON v.nummer_id = n.id
212230
LEFT JOIN panden p ON v.pand_id = p.id;
213231
""")
214232

233+
utils.print_log('create adressen tabel: import ligplaatsen data')
215234
self.adressen_import_ligplaatsen()
235+
236+
utils.print_log('create adressen tabel: import standplaatsen data')
216237
self.adressen_import_standplaatsen()
238+
239+
utils.print_log('create adressen tabel: import woonplaatsen from nummers')
217240
self.adressen_update_woonplaatsen_from_nummers()
241+
242+
utils.print_log('create adressen tabel: update nevenadressen data')
243+
self.adressen_update_nevenadressen()
244+
245+
utils.print_log('create adressen tabel: create indices')
218246
self.create_indices_adressen()
219247

220248
self.connection.commit()
@@ -245,7 +273,41 @@ def adressen_import_standplaatsen(self):
245273
WHERE s.nummer_id = adressen.nummer_id;
246274
""")
247275

248-
# woonplaats_id in nummers overruled woonplaats_id van de openbare ruimte.
276+
def adressen_update_nevenadressen(self):
277+
self.connection.executescript("""
278+
UPDATE adressen SET
279+
hoofd_nummer_id = n.hoofd_nummer_id,
280+
pand_id = n.pand_id,
281+
verblijfsobject_id = n.verblijfsobject_id,
282+
gebruiksdoel = n.gebruiksdoel,
283+
oppervlakte = n.oppervlakte,
284+
rd_x = n.rd_x,
285+
rd_y = n.rd_y,
286+
latitude = n.latitude,
287+
longitude = n.longitude,
288+
bouwjaar = n.bouwjaar,
289+
geometry = n.geometry
290+
FROM (
291+
SELECT
292+
nevenadressen.hoofd_nummer_id,
293+
nevenadressen.neven_nummer_id,
294+
adressen.pand_id,
295+
adressen.verblijfsobject_id,
296+
adressen.gebruiksdoel,
297+
adressen.oppervlakte,
298+
adressen.rd_x,
299+
adressen.rd_y,
300+
adressen.latitude,
301+
adressen.longitude,
302+
adressen.bouwjaar,
303+
adressen.geometry
304+
FROM nevenadressen
305+
LEFT JOIN adressen ON nevenadressen.hoofd_nummer_id = adressen.nummer_id
306+
) AS n
307+
WHERE n.neven_nummer_id = adressen.nummer_id;
308+
""")
309+
310+
# woonplaats_id in nummers overrule woonplaats_id van de openbare ruimte.
249311
def adressen_update_woonplaatsen_from_nummers(self):
250312
self.connection.executescript("""
251313
UPDATE adressen SET
@@ -258,6 +320,7 @@ def delete_no_longer_needed_bag_tables(self):
258320
self.connection.executescript("""
259321
DROP TABLE IF EXISTS nummers;
260322
DROP TABLE IF EXISTS panden;
323+
DROP TABLE IF EXISTS nevenadressen;
261324
DROP TABLE IF EXISTS verblijfsobjecten;
262325
DROP TABLE IF EXISTS ligplaatsen;
263326
DROP TABLE IF EXISTS standplaatsen;
@@ -344,7 +407,7 @@ def test_bag_adressen(self):
344407

345408
# Het is makkelijk om per ongeluk een gemeenten.csv te genereren die niet in UTF-8 is. Testen dus.
346409
naam = self.fetchone("SELECT naam FROM gemeenten WHERE id=1900")
347-
utils.print_log("test: Gemeentenamen moeten in UTF-8 zijn: " + naam, naam != 'Súdwest-Fryslân')
410+
utils.print_log("test: gemeentenamen moeten in UTF-8 zijn: " + naam, naam != 'Súdwest-Fryslân')
348411

349412
aantal = self.fetchone("SELECT COUNT(*) FROM adressen WHERE adressen.latitude IS NULL AND pand_id IS NOT NULL;")
350413
utils.print_log("test: panden zonder locatie: " + str(aantal), aantal > 0)

import_bag.py

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
db_sqlite.create_indices_bag()
4848

4949
if config. create_adressen_table:
50-
utils.print_log('create adressen tabel')
5150
db_sqlite.create_adressen_from_bag()
5251
db_sqlite.adressen_fix_bag_errors()
5352
db_sqlite.test_bag_adressen()

0 commit comments

Comments
 (0)