]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/api/v1/format_xml.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / nominatim / api / v1 / format_xml.py
index b1159f939949187ab024fe4224fd85018b765de3..c6ea17c01f9a4559bfb7ca1529a4212059daac65 100644 (file)
@@ -7,23 +7,27 @@
 """
 Helper functions for output of results in XML format.
 """
 """
 Helper functions for output of results in XML format.
 """
-from typing import Mapping, Any, Optional
+from typing import Mapping, Any, Optional, Union
 import datetime as dt
 import xml.etree.ElementTree as ET
 
 import nominatim.api as napi
 import datetime as dt
 import xml.etree.ElementTree as ET
 
 import nominatim.api as napi
-from nominatim.api.v1.constants import OSM_ATTRIBUTION, OSM_TYPE_NAME, bbox_from_result
-from nominatim.api.v1.classtypes import ICONS, get_label_tag
+import nominatim.api.v1.classtypes as cl
+
+#pylint: disable=too-many-branches
 
 def _write_xml_address(root: ET.Element, address: napi.AddressLines,
                        country_code: Optional[str]) -> None:
     parts = {}
     for line in address:
 
 def _write_xml_address(root: ET.Element, address: napi.AddressLines,
                        country_code: Optional[str]) -> None:
     parts = {}
     for line in address:
-        if line.isaddress and line.local_name:
-            label = get_label_tag(line.category, line.extratags,
-                                  line.rank_address, country_code)
-            if label not in parts:
-                parts[label] = line.local_name
+        if line.isaddress:
+            if line.local_name:
+                label = cl.get_label_tag(line.category, line.extratags,
+                                         line.rank_address, country_code)
+                if label not in parts:
+                    parts[label] = line.local_name
+            if line.names and 'ISO3166-2' in line.names and line.admin_level:
+                parts[f"ISO3166-2-lvl{line.admin_level}"] = line.names['ISO3166-2']
 
     for k,v in parts.items():
         ET.SubElement(root, k).text = v
 
     for k,v in parts.items():
         ET.SubElement(root, k).text = v
@@ -32,30 +36,27 @@ def _write_xml_address(root: ET.Element, address: napi.AddressLines,
         ET.SubElement(root, 'country_code').text = country_code
 
 
         ET.SubElement(root, 'country_code').text = country_code
 
 
-def _create_base_entry(result: napi.ReverseResult, #pylint: disable=too-many-branches
-                       root: ET.Element, simple: bool,
-                       locales: napi.Locales) -> ET.Element:
-    if result.address_rows:
-        label_parts = result.address_rows.localize(locales)
-    else:
-        label_parts = []
-
+def _create_base_entry(result: Union[napi.ReverseResult, napi.SearchResult],
+                       root: ET.Element, simple: bool) -> ET.Element:
     place = ET.SubElement(root, 'result' if simple else 'place')
     if result.place_id is not None:
         place.set('place_id', str(result.place_id))
     if result.osm_object:
     place = ET.SubElement(root, 'result' if simple else 'place')
     if result.place_id is not None:
         place.set('place_id', str(result.place_id))
     if result.osm_object:
-        osm_type = OSM_TYPE_NAME.get(result.osm_object[0], None)
+        osm_type = cl.OSM_TYPE_NAME.get(result.osm_object[0], None)
         if osm_type is not None:
             place.set('osm_type', osm_type)
         place.set('osm_id', str(result.osm_object[1]))
     if result.names and 'ref' in result.names:
         if osm_type is not None:
             place.set('osm_type', osm_type)
         place.set('osm_id', str(result.osm_object[1]))
     if result.names and 'ref' in result.names:
-        place.set('place_id', result.names['ref'])
-    place.set('lat', str(result.centroid.lat))
-    place.set('lon', str(result.centroid.lon))
+        place.set('ref', result.names['ref'])
+    elif result.locale_name:
+        # bug reproduced from PHP
+        place.set('ref', result.locale_name)
+    place.set('lat', f"{result.centroid.lat:.7f}")
+    place.set('lon', f"{result.centroid.lon:.7f}")
 
 
-    bbox = bbox_from_result(result)
-    place.set('boundingbox', ','.join(map(str, [bbox.minlat, bbox.maxlat,
-                                                bbox.minlon, bbox.maxlon])))
+    bbox = cl.bbox_from_result(result)
+    place.set('boundingbox',
+              f"{bbox.minlat:.7f},{bbox.maxlat:.7f},{bbox.minlon:.7f},{bbox.maxlon:.7f}")
 
     place.set('place_rank', str(result.rank_search))
     place.set('address_rank', str(result.rank_address))
 
     place.set('place_rank', str(result.rank_search))
     place.set('address_rank', str(result.rank_address))
@@ -71,9 +72,9 @@ def _create_base_entry(result: napi.ReverseResult, #pylint: disable=too-many-bra
             place.set('geojson', result.geometry['geojson'])
 
     if simple:
             place.set('geojson', result.geometry['geojson'])
 
     if simple:
-        place.text = ', '.join(label_parts)
+        place.text = result.display_name or ''
     else:
     else:
-        place.set('display_name', ', '.join(label_parts))
+        place.set('display_name', result.display_name or '')
         place.set('class', result.category[0])
         place.set('type', result.category[1])
         place.set('importance', str(result.calculated_importance()))
         place.set('class', result.category[0])
         place.set('type', result.category[1])
         place.set('importance', str(result.calculated_importance()))
@@ -81,18 +82,16 @@ def _create_base_entry(result: napi.ReverseResult, #pylint: disable=too-many-bra
     return place
 
 
     return place
 
 
-def format_base_xml(results: napi.ReverseResults,
+def format_base_xml(results: Union[napi.ReverseResults, napi.SearchResults],
                     options: Mapping[str, Any],
                     simple: bool, xml_root_tag: str,
                     xml_extra_info: Mapping[str, str]) -> str:
     """ Format the result into an XML response. With 'simple' exactly one
         result will be output, otherwise a list.
     """
                     options: Mapping[str, Any],
                     simple: bool, xml_root_tag: str,
                     xml_extra_info: Mapping[str, str]) -> str:
     """ Format the result into an XML response. With 'simple' exactly one
         result will be output, otherwise a list.
     """
-    locales = options.get('locales', napi.Locales())
-
     root = ET.Element(xml_root_tag)
     root.set('timestamp', dt.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S +00:00'))
     root = ET.Element(xml_root_tag)
     root.set('timestamp', dt.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S +00:00'))
-    root.set('attribution', OSM_ATTRIBUTION)
+    root.set('attribution', cl.OSM_ATTRIBUTION)
     for k, v in xml_extra_info.items():
         root.set(k, v)
 
     for k, v in xml_extra_info.items():
         root.set(k, v)
 
@@ -100,10 +99,10 @@ def format_base_xml(results: napi.ReverseResults,
         ET.SubElement(root, 'error').text = 'Unable to geocode'
 
     for result in results:
         ET.SubElement(root, 'error').text = 'Unable to geocode'
 
     for result in results:
-        place = _create_base_entry(result, root, simple, locales)
+        place = _create_base_entry(result, root, simple)
 
         if not simple and options.get('icon_base_url', None):
 
         if not simple and options.get('icon_base_url', None):
-            icon = ICONS.get(result.category)
+            icon = cl.ICONS.get(result.category)
             if icon:
                 place.set('icon', icon)
 
             if icon:
                 place.set('icon', icon)