1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
<?xml version="1.0" encoding="UTF-8"?>
{#
This is a Jinja2 template for generating one of the most complex INSPIRE Schema's: Annex I Addresses specified in
http://inspire.jrc.ec.europa.eu/documents/Data_Specifications/INSPIRE_DataSpecification_AD_v3.1.pdf
The GML Application Schema is complex and verbose, but the actual required input is quite small.
At a minimum just 4 variables for a complete address: street, house number, postal code, city plus a point (lat,lon)
for each address. This makes Templating so powerful. The input in Stetl are both records (an array of records (dict's)
called "addresses" originating from a CSV (here addresses.csv) or possibly some database records. The other input is a
JSON file (addresses-globals.json) with global static variables, called "globs" below. The output is plain GML according to
the XSD http://inspire.ec.europa.eu/schemas/ad/3.0/Addresses.xsd to which the output also validates. Note the verbosity:
a one-line CSV address expands to 100 lines/elements of uncommented GML
#}
{# Macro's, a very powerful reuse mechanism, e.g. for common elements and structures like INSPIRE id and GeographicalName's. #}
{% import 'templates/macros-inspire.jinja2' as macros_inspire %}
<base:SpatialDataSet xmlns:base="urn:x-inspire:specification:gmlas:BaseTypes:3.2"
xmlns:AD="urn:x-inspire:specification:gmlas:Addresses:3.0"
xmlns:GN="urn:x-inspire:specification:gmlas:GeographicalNames:3.0"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gml="http://www.opengis.net/gml/3.2"
xsi:schemaLocation="urn:x-inspire:specification:gmlas:BaseTypes:3.2 http://inspire.ec.europa.eu/schemas/base/3.2/BaseTypes.xsd
urn:x-inspire:specification:gmlas:Addresses:3.0 http://inspire.ec.europa.eu/schemas/ad/3.0/Addresses.xsd
urn:x-inspire:specification:gmlas:GeographicalNames:3.0 http://inspire.ec.europa.eu/schemas/gn/3.0/GeographicalNames.xsd"
gml:id="{{ globs.namespace }}">
<base:identifier>
<base:Identifier>
<base:localId>0</base:localId>
<base:namespace>{{ globs.namespace }}</base:namespace>
</base:Identifier>
</base:identifier>
<base:metadata xsi:nil="true"/>
{# Tracking for Address components that should appear only once, as they are xlinked as AD:component-s #}
{% set cities = {} %}
{% set streets = {} %}
{% set postal_codes = {} %}
{% for address in addresses %}
<base:member>
<AD:Address gml:id="{{ globs.namespace }}.Address.{{ address.address_id }}">
<gml:identifier
codeSpace="{{ globs.inspire_codespace_uri }}">{{ globs.inspire_urn_prefix_id }}:{{ globs.namespace }}.Address.{{ address.address_id }}</gml:identifier>
<AD:inspireId>
{{ macros_inspire.render_inspire_id(globs.namespace, address.address_id) }}
</AD:inspireId>
<AD:position>
<AD:GeographicPosition>
<AD:geometry>
<gml:Point gml:id="{{ globs.namespace }}.Address.{{ address.address_id }}_P"
srsName="{{ globs.srs_name }}">
<gml:pos>{{ address.lat }} {{ address.lon }}</gml:pos>
</gml:Point>
</AD:geometry>
<AD:specification>entrance</AD:specification>
<AD:method>byOtherParty</AD:method>
<AD:default>true</AD:default>
</AD:GeographicPosition>
</AD:position>
<AD:locator>
<AD:AddressLocator>
{# In the Netherlands a house number is always required #}
<AD:designator>
<AD:LocatorDesignator>
<AD:designator>{{ address.house_number }}</AD:designator>
<AD:type>{{ globs.locator_designator.house_number }}</AD:type>
</AD:LocatorDesignator>
</AD:designator>
{% if address.house_letter %}
<!-- Optional House Letter Addition, e.g. "Huisletter" in The Netherlands -->
<AD:designator>
<AD:LocatorDesignator>
<AD:designator>{{ address.house_letter }}</AD:designator>
<AD:type>{{ globs.locator_designator.house_letter }}</AD:type>
</AD:LocatorDesignator>
</AD:designator>
{% endif %}
{% if address.house_number_add %}
<!-- Optional House Number Addition, e.g. Floornumber "Huisnummertoevoeging" in The Netherlands -->
<AD:designator>
<AD:LocatorDesignator>
<AD:designator>{{ address.house_number_add }}</AD:designator>
<AD:type>{{ globs.locator_designator.house_number_add }}</AD:type>
</AD:LocatorDesignator>
</AD:designator>
{% endif %}
<AD:level>unitLevel</AD:level>
</AD:AddressLocator>
</AD:locator>
<AD:validFrom>{{ globs.valid_from }}</AD:validFrom>
<AD:validTo xsi:nil="true" nilReason="other:unpopulated"/>
<AD:beginLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:endLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<!-- Inline reference to address components: street (ThoroughfareName_, city (AddressAreaName)
and postal code (PostalDescriptor) -->
<AD:component xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="#{{ globs.namespace }}.ThoroughfareName.{{ address.street_id }}"/>
<AD:component xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="#{{ globs.namespace }}.AddressAreaName.{{ address.city_id }}"/>
<AD:component xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="#{{ globs.namespace }}.PostalDescriptor.{{ address.postal_code }}"/>
</AD:Address>
</base:member>
{% if streets[address.street_id] is not defined %}
{# Each street (BAG id) may appear only once within the Spatial Dataset.
Track the unique street id in a map (dict) and check below to add only once. #}
{% do streets.update({address.street_id:address.street_id}) %}
<base:member>
<AD:ThoroughfareName gml:id="{{ globs.namespace }}.ThoroughfareName.{{ address.street_id }}">
<gml:identifier codeSpace="{{ globs.inspire_codespace_uri }}">
{{ globs.inspire_urn_prefix_id }}:{{ globs.namespace }}.ThoroughfareName.{{ address.street_id }}
</gml:identifier>
<AD:inspireId>
{{ macros_inspire.render_inspire_id(globs.namespace, address.street_id) }}
</AD:inspireId>
<AD:beginLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:endLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:validFrom>{{ globs.valid_from }}</AD:validFrom>
<AD:validTo xsi:nil="true" nilReason="other:unpopulated"/>
<AD:name>
<AD:ThoroughfareNameValue>
<AD:name>
{{ macros_inspire.render_geographical_name(address.street_name, globs.geographical_name) }}
</AD:name>
</AD:ThoroughfareNameValue>
</AD:name>
</AD:ThoroughfareName>
</base:member>
{% endif %}
{% if cities[address.city_id] is not defined %}
{# Each city may appear only once within the Spatial Dataset.
Track the unique city id in a map (dict) and check below to add only once. #}
{% do cities.update({address.city_id:address.city_id}) %}
<base:member>
<AD:AddressAreaName gml:id="{{ globs.namespace }}.AddressAreaName.{{ address.city_id }}">
<gml:identifier codeSpace="{{ globs.inspire_codespace_uri }}">
{{ globs.inspire_urn_prefix_id }}:{{ globs.namespace }}.AddressAreaName.{{ address.city_id }}
</gml:identifier>
<AD:inspireId>
{{ macros_inspire.render_inspire_id(globs.namespace, address.city_id) }}
</AD:inspireId>
<AD:beginLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:endLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:validFrom>{{ globs.valid_from }}</AD:validFrom>
<AD:validTo xsi:nil="true" nilReason="other:unpopulated"/>
<AD:name>
{{ macros_inspire.render_geographical_name(address.city_name, globs.geographical_name) }}
</AD:name>
<AD:namedPlace xsi:nil="true" nilReason="other:unpopulated"/>
</AD:AddressAreaName>
</base:member>
{% endif %}
{% if postal_codes[address.postal_code] is not defined %}
{# Each postal code (NL Postcode) may appear only once within the Spatial Dataset.
Track the unique posatl codes id in a map (dict) and check below to add only once. #}
{% do postal_codes.update({address.postal_code:address.postal_code}) %}
<base:member>
<AD:PostalDescriptor gml:id="{{ globs.namespace }}.PostalDescriptor.{{ address.postal_code }}">
<gml:identifier codeSpace="{{ globs.inspire_codespace_uri }}">
{{ globs.inspire_urn_prefix_id }}:{{ globs.namespace }}.PostalDescriptor.{{ address.postal_code }}
</gml:identifier>
<AD:inspireId>
{{ macros_inspire.render_inspire_id(globs.namespace, address.postal_code) }}
</AD:inspireId>
<AD:beginLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:endLifespanVersion xsi:nil="true" nilReason="other:unpopulated"/>
<AD:validFrom>{{ globs.valid_from }}</AD:validFrom>
<AD:validTo xsi:nil="true" nilReason="other:unpopulated"/>
<AD:postCode>{{ address.postal_code }}</AD:postCode>
</AD:PostalDescriptor>
</base:member>
{% endif %}
{% endfor %}
</base:SpatialDataSet>
|