diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bb48ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +syntax: glob +*.pyc +*.egg-info +*.orig +.coverage +build +*.egg +.DS_Store +dist +development.ini +.DS_Store +*.swp +*~ diff --git a/ckanext/__init__.py b/ckanext/__init__.py new file mode 100644 index 0000000..2e2033b --- /dev/null +++ b/ckanext/__init__.py @@ -0,0 +1,7 @@ +# this is a namespace package +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/ckanext/swisstopo/__init__.py b/ckanext/swisstopo/__init__.py new file mode 100644 index 0000000..2e2033b --- /dev/null +++ b/ckanext/swisstopo/__init__.py @@ -0,0 +1,7 @@ +# this is a namespace package +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/ckanext/swisstopo/ckan_csw/__init__.py b/ckanext/swisstopo/ckan_csw/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ckanext/swisstopo/ckan_csw/ckan_csw.py b/ckanext/swisstopo/ckan_csw/ckan_csw.py new file mode 100644 index 0000000..a808926 --- /dev/null +++ b/ckanext/swisstopo/ckan_csw/ckan_csw.py @@ -0,0 +1,241 @@ +import traceback +from owslib.csw import CatalogueServiceWeb +from ckanext.swisstopo.etree.etree import etree + +namespaces = { + 'atom': 'http://www.w3.org/2005/Atom', + 'che': 'http://www.geocat.ch/2008/che', + 'csw': 'http://www.opengis.net/cat/csw/2.0.2', + 'dc' : 'http://purl.org/dc/elements/1.1/', + 'dct': 'http://purl.org/dc/terms/', + 'dif': 'http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/', + 'fgdc': 'http://www.opengis.net/cat/csw/csdgm', + 'gco': 'http://www.isotc211.org/2005/gco', + 'gmd': 'http://www.isotc211.org/2005/gmd', + 'gml': 'http://www.opengis.net/gml', + 'ogc': 'http://www.opengis.net/ogc', + 'ows': 'http://www.opengis.net/ows', + 'rim': 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0', + 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'xs' : 'http://www.w3.org/2001/XMLSchema', + 'xs2': 'http://www.w3.org/XML/Schema', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance' +} + +class Attribute(object): + def __init__(self, config, **kwargs): + self._config = config + self.env = kwargs + + def get_value(self, **kwargs): + """ Abstract method to return the value of the attribute """ + raise NotImplementedError + +class StringAttribute(Attribute): + def get_value(self, **kwargs): + return self._config + +class XmlAttribute(Attribute): + def get_value(self, **kwargs): + self.env.update(kwargs) + xml = self.env['xml'] + return etree.tostring(xml) + +class XPathAttribute(Attribute): + def get_element(self, xml): + return xml.find(self._config, namespaces) + + def get_value(self, **kwargs): + self.env.update(kwargs) + xml = self.env['xml'] + try: + # this should probably return a XPathTextAttribute + value = self.get_element(xml) + except: + value = '' + return value + +class XPathMultiAttribute(XPathAttribute): + def get_element(self, xml): + return xml.findall(self._config, namespaces) + +class XPathTextAttribute(XPathAttribute): + def get_value(self, **kwargs): + value = super(XPathTextAttribute, self).get_value(**kwargs) + return value.text if hasattr(value, 'text') else value + +class XPathMultiTextAttribute(XPathMultiAttribute): + def get_value(self, **kwargs): + value = super(XPathMultiTextAttribute, self).get_value(**kwargs) + return value.text if hasattr(value, 'text') else value + +class CombinedAttribute(Attribute): + def get_value(self, **kwargs): + self.env.update(kwargs) + value = '' + separator = self.env['separator'] if self.env.has_key('separator') else ' ' + for attribute in self._config: + new_value = attribute.get_value(**kwargs) + value = value + attribute.get_value(**kwargs) + separator if new_value != None else value + return value.strip(separator) + +class MultiAttribute(Attribute): + def get_value(self, **kwargs): + self.env.update(kwargs) + value = '' + separator = self.env['separator'] if self.env.has_key('separator') else ' ' + for attribute in self._config: + new_value = attribute.get_value(**kwargs) + try: + iterator = iter(new_value) + for inner_attribute in iterator: + # it should be possible to call inner_attribute.get_value and the right thing(tm) happens' + value = value + (inner_attribute.text if hasattr(inner_attribute, 'text') else inner_attribute) + separator + except TypeError: + value = value + new_value + separator + return value.strip(separator) + + +class FirstInOrderAttribute(CombinedAttribute): + def get_value(self, **kwargs): + for attribute in self._config: + value = attribute.get_value(**kwargs) + if value != '': + return value + return '' + +class CkanMetadata(object): + """ Provides general access to CSW for CKAN """ + def __init__(self, url, schema, version='2.0.2', lang='en-US'): + self.schema = schema + self.catalog = CatalogueServiceWeb(url, lang, version, timeout=10, skip_caps=True) + self.metadata = dict.fromkeys([ + 'id', + 'name', + 'title', + 'url', + 'author', + 'author_email', + 'maintainer', + 'maintainer_email', + 'license', + 'version', + 'notes', + 'tags', + 'metadata_url', + 'metadata_raw', + ]) + + def get_by_search(self, searchterm, propertyname='csw:AnyText'): + """ Returns the found csw dataset with the given searchterm """ + self.catalog.getrecords(keywords=[searchterm], propertyname=propertyname) + if self.catalog.response == None or self.catalog.results['matches'] == 0: + raise DatasetNotFoundError("No dataset for the given searchterm '%s' (%s) found" % (searchterm, propertyname)) + return self.catalog.records + + def get_by_id(self, id): + """ Returns the csw dataset with the given id """ + self.catalog.getrecordbyid(id=[id], outputschema=self.schema) + return self.catalog.response + + def get_id_by_dataset_name(self, dataset_name): + """ + Returns the id of a dataset identified by it's name. + If there are multiple datasets with the given name, + only the id of the first one is returned. + """ + return self.get_by_search(dataset_name, 'title').itervalues().next().identifier + + def get_attribute(self, dataset_name, ckan_attribute): + """ Abstract method to define the mapping of a ckan attribute to a csw attribute """ + raise NotImplementedError + + def get_xml(self, id): + dataset_xml_string = self.get_by_id(id) + if dataset_xml_string == None: + raise DatasetNotFoundError("Dataset with id %s not found" % id) + return dataset_xml_string + + def get_ckan_metadata(self, dataset_name): + """ Returns the requested dataset mapped to CKAN attributes """ + id = self.get_id_by_dataset_name(dataset_name) + dataset_xml = etree.fromstring(self.get_xml(id)) + for key in self.metadata: + attribute = self.get_attribute(dataset_name, key) + self.metadata[key] = attribute.get_value(xml=dataset_xml) + return self.metadata + + +class SwisstopoCkanMetadata(CkanMetadata): + """ Provides access to the csw service of swisstopo """ + + default_mapping = { + 'id': XPathTextAttribute('.//gmd:fileIdentifier/gco:CharacterString'), + 'name': XPathTextAttribute(".//gmd:identificationInfo//gmd:citation//gmd:title//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']"), + 'title': XPathTextAttribute(".//gmd:identificationInfo//gmd:citation//gmd:alternateTitle//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']"), + 'url': XPathTextAttribute(".//gmd:distributionInfo//gmd:transferOptions//gmd:onLine//gmd:linkage//che:URLGroup/che:LocalisedURL[@locale='#DE']"), + 'author': CombinedAttribute([ + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//che:individualFirstName/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//che:individualLastName/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//gmd:organisationName//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']") + ]), + 'author_email': FirstInOrderAttribute([ + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='author']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='originator']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='owner']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='pointOfContact']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + ]), + 'maintainer': CombinedAttribute([ + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//che:individualFirstName/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//che:individualLastName/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//gmd:organisationName//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']") + ]), + 'maintainer_email': FirstInOrderAttribute([ + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='publisher']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='custodian']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='distributor']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='pointOfContact']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact[1]//gmd:CI_RoleCode[@codeListValue='owner']/ancestor::gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + XPathTextAttribute(".//gmd:identificationInfo//gmd:pointOfContact//gmd:address//gmd:electronicMailAddress/gco:CharacterString"), + ]), + 'license': StringAttribute('http://www.toposhop.admin.ch/de/shop/terms/use/finished_products'), + 'version': XPathTextAttribute(".//gmd:identificationInfo//gmd:citation//gmd:date/gco:Date"), + 'notes': XPathTextAttribute(".//gmd:identificationInfo//gmd:abstract//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']"), + 'tags': MultiAttribute([XPathMultiTextAttribute(".//gmd:identificationInfo//gmd:descriptiveKeywords//gmd:keyword//gmd:textGroup/gmd:LocalisedCharacterString[@locale='#DE']")], separator=' '), + 'metadata_url': StringAttribute(''), + 'metadata_raw': XmlAttribute(''), + } + + known_datasets = { + 'swissboundaries3D': { + 'id': '86cb844f-296b-40cb-b972-5b1ae8028f7c', + 'mapping': default_mapping + } + } + + + def __init__(self, url='http://www.geocat.ch/geonetwork/srv/eng/csw?', schema='http://www.geocat.ch/2008/che', version='2.0.2', lang='en-US'): + super(SwisstopoCkanMetadata, self).__init__(url,schema,version,lang) + + def get_id_by_dataset_name(self, dataset_name): + if (dataset_name in self.known_datasets): + return self.known_datasets[dataset_name]['id'] + return super(SwisstopoCkanMetadata, self).get_id_by_dataset_name(dataset_name) + + def get_mapping(self, dataset_name): + if dataset_name in self.known_datasets and 'mapping' in self.known_datasets[dataset_name]: + return self.known_datasets[dataset_name]['mapping']; + return self.default_mapping + + def get_attribute(self, dataset_name, ckan_attribute): + mapping = self.get_mapping(dataset_name) + if ckan_attribute in mapping: + return mapping[ckan_attribute] + raise AttributeMappingNotFoundError("No mapping found for attribute '%s'" % ckan_attribute) + +class DatasetNotFoundError(Exception): + pass + +class AttributeMappingNotFoundError(Exception): + pass diff --git a/ckanext/swisstopo/ckan_csw/run_ckan_csw.py b/ckanext/swisstopo/ckan_csw/run_ckan_csw.py new file mode 100644 index 0000000..851ee60 --- /dev/null +++ b/ckanext/swisstopo/ckan_csw/run_ckan_csw.py @@ -0,0 +1,8 @@ +from ckanext.swisstopo.ckan_csw import ckan_csw +from pprint import pprint + +swisstopo = ckan_csw.SwisstopoCkanMetadata() + +pprint(swisstopo) + +pprint(swisstopo.get_ckan_metadata('swissboundaries3D')) diff --git a/ckanext/swisstopo/cleanup.py b/ckanext/swisstopo/cleanup.py new file mode 100644 index 0000000..c321a66 --- /dev/null +++ b/ckanext/swisstopo/cleanup.py @@ -0,0 +1,29 @@ +import ckanclient +import sys +from optparse import OptionParser +from pprint import pprint + +API_KEY = p.toolkit.asbool(config.get('ckanext.swisstopo.api_key', '')) +BASE_LOCATION = p.toolkit.asbool(config.get('ckanext.swisstopo.base_location', '')) + +ckan = ckanclient.CkanClient(api_key=API_KEY, base_location=BASE_LOCATION) + +parser = OptionParser() +parser.add_option("-s", "--search", dest="search_term", help="search packages with TERM", metavar="TERM") +parser.add_option("-t", "--tag", dest="search_tag", help="Search packages with tag TAG", metavar="TAG") +(options, args) = parser.parse_args() + +results = [] +if options.search_term: + search_results = ckan.package_search(options.search_term); + results = search_results['results'] +elif options.search_tag: + search_results = ckan.package_search('tags:' + options.search_tag); + results = search_results['results'] +else: + parser.error("No valid argument supplied") + +for package_name in results: + print package_name + last_message = ckan.package_entity_delete(package_name) + print last_message diff --git a/ckanext/swisstopo/commands/__init__.py b/ckanext/swisstopo/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ckanext/swisstopo/commands/swisstopo.py b/ckanext/swisstopo/commands/swisstopo.py new file mode 100644 index 0000000..4f07dcb --- /dev/null +++ b/ckanext/swisstopo/commands/swisstopo.py @@ -0,0 +1,38 @@ +import logging +import ckan.lib.cli + +class SwisstopoCommand(ckan.lib.cli.CkanCommand): + '''Command to import swisstopo data + + Usage:: + + From the ckanext-swisstopo directory, run: + + paster swisstopo import -c + + ''' + summary = __doc__.split('\n')[0] + usage = __doc__ + + def command(self): + options = { + 'import': self.importCmd, + 'show': self.showCmd, + 'help': self.helpCmd, + } + + try: + cmd = self.args[0] + options[cmd]() + except KeyError: + helpCmd() + + def helpCmd(self): + print self.__doc__ + + def importCmd(self): + raise NotImplementedError + + def showCmd(self): + raise NotImplementedError + diff --git a/ckanext/swisstopo/etree/__init__.py b/ckanext/swisstopo/etree/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ckanext/swisstopo/etree/etree.py b/ckanext/swisstopo/etree/etree.py new file mode 100644 index 0000000..fb7ac43 --- /dev/null +++ b/ckanext/swisstopo/etree/etree.py @@ -0,0 +1,54 @@ +# ============================================================================= +# OWSLib. Copyright (C) 2005 Sean C. Gillies +# +# Contact email: sgillies@frii.com +# ============================================================================= + +def patch_well_known_namespaces(etree_module): + """Monkey patches the etree module to add some well-known namespaces.""" + etree_module._namespace_map.update({ + "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf", + "http://purl.org/rss/1.0/": "rss", + "http://purl.org/rss/1.0/modules/taxonomy/": "taxo", + "http://purl.org/dc/elements/1.1/": "dc", + "http://purl.org/rss/1.0/modules/syndication/": "syn", + "http://www.w3.org/2003/01/geo/wgs84_pos#": "geo", + "http://www.opengis.net/cat/csw/2.0.2": "csw", + "http://purl.org/dc/terms/": "dct", + "http://www.isotc211.org/2005/gco": "gco", + "http://www.isotc211.org/2005/gmd": "gmd", + "http://www.geocat.ch/2008/che": "che", + "http://www.isotc211.org/2005/gts": "gts", + "http://www.isotc211.org/2005/srv": "srv", + "http://www.fgdc.gov": "fgdc", + "http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/": "dif", + "http://www.opengis.net/gml": "gml", + "http://www.opengis.net/ogc": "ogc", + "http://www.opengis.net/ows": "ows", + "http://www.opengis.net/ows/1.1": "ows", + "http://www.opengis.net/ows/2.0": "ows", + "http://www.opengis.net/wms": "wms", + "http://www.opengis.net/context": "wmc", + "http://www.opengis.net/wfs": "wfs", + "http://www.opengis.net/sos/1.0": "sos", + "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0": "rim", + "http://www.w3.org/2001/XMLSchema": "xs", + "http://www.w3.org/XML/Schema": "xs2", + "http://www.w3.org/2001/XMLSchema-instance": "xsi", + "http://www.w3.org/1999/xlink": "xlink"}) + +# try to find lxml or elementtree +try: + from lxml import etree +except ImportError: + try: + # Python 2.5 with ElementTree included + import xml.etree.ElementTree as etree + patch_well_known_namespaces(etree) + except ImportError: + try: + # Python < 2.5 with ElementTree installed + import elementtree.ElementTree as etree + patch_well_known_namespaces(etree) + except ImportError: + raise RuntimeError('You need either lxml or ElementTree to use OWSLib!') diff --git a/ckanext/swisstopo/s3/__init__.py b/ckanext/swisstopo/s3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ckanext/swisstopo/s3/s3_ls.py b/ckanext/swisstopo/s3/s3_ls.py new file mode 100644 index 0000000..0d36d8e --- /dev/null +++ b/ckanext/swisstopo/s3/s3_ls.py @@ -0,0 +1,10 @@ +from boto.s3.connection import S3Connection + +S3_KEY = p.toolkit.asbool(config.get('ckanext.swisstopo.s3_key', '')) +S3_TOKEN = p.toolkit.asbool(config.get('ckanext.swisstopo.s3_token', '')) +S3_BUCKET = p.toolkit.asbool(config.get('ckanext.swisstopo.s3_bucket', '')) + +conn = S3Connection(S3_KEY,S3_TOKEN) +bucket = conn.get_bucket(S3_BUCKET) +for key in bucket.list(): + print key.name.encode('utf-8') diff --git a/ckanext/swisstopo/s3/s3_upload.py b/ckanext/swisstopo/s3/s3_upload.py new file mode 100644 index 0000000..d671693 --- /dev/null +++ b/ckanext/swisstopo/s3/s3_upload.py @@ -0,0 +1,81 @@ +import ckanclient +import urllib +import os +from httplib2 import Http +from datetime import datetime + +API_KEY = p.toolkit.asbool(config.get('ckanext.swisstopo.api_key', '')) +BASE_LOCATION = p.toolkit.asbool(config.get('ckanext.swisstopo.base_location', '')) + +ckan = ckanclient.CkanClient(api_key=API_KEY, base_location=BASE_LOCATION) + +now = datetime.now() + +# Register the dataset. +dataset_name = 's3_test_dataset_' + now.strftime("%Y-%m-%d_%H-%M-%S") +# csv_url = 'https://commondatastorage.googleapis.com/ckannet-storage/2011-11-24T112025/AfTerFibre_21nov2011.csv' +dataset_entity = { + 'name': dataset_name, + 'tags': 'test', + 'notes': 'Notes about the test', + } + +package_response = ckan.package_register_post(dataset_entity) +print "package_response start" +print package_response +print "package_response end" + +# Download the file +# file_name = csv_url.split('/')[-1] +file_name = 'sample.csv' +# urllib.urlretrieve (csv_url, file_name) + +# Upload the file +res1, res2 = ckan.upload_file(file_name) +print res1 +print res2 + +# ------------- + +# import ckanclient +# import urllib +# +# ckan = ckanclient.CkanClient(api_key=API_KEY, base_location=BASE_LOCATION) +# +# # dataset_name = 'phils_dataset_2013-02-19_23-44-42' +# dataset_name = 'new_liip_dataset' +# # file_name = 'sample.csv' +# # file_name = 'http://ckan.liip.ch.s3.amazonaws.com/2013-02-19T234442/sample.csv' +# # res1 = ckan.add_package_resource(dataset_name, file_name, resource_type='csv', description='Some CSV') +# +# res1 = ckan.add_package_resource(dataset_name, 'sample.csv', resource_type='data', description='this-is-a-description') +# print res1 +# res2 = ckan.add_package_resource(dataset_name, 'http://ckan.liip.ch.s3.amazonaws.com/2013-02-20T003611/sample.csv', name='Foo', resource_type='metadata', format='csv') +# print res2 + +# ------------- + +# url = 'http://ckan.liip.ch.s3.amazonaws.com/' + +# from poster.encode import multipart_encode +# from poster.streaminghttp import register_openers +# import urllib2 + +# register_openers() + +# datagen, headers = multipart_encode({ +# 'key': '2013-02-19T224240/sample.csv', +# 'acl': 'public-read', +# 'AWSAccessKeyId': 'AKIAIIHWI2WETQQMAW5Q', +# 'policy': 'eyJleHBpcmF0aW9uIjogIjIwMTMtMDItMjBUMTc6NDI6MzhaIiwKImNvbmRpdGlvbnMiOiBbeyJ4LWFtei1tZXRhLXVwbG9hZGVkLWJ5IjogIjc0NmIyYzU4LWU3NGYtNDZhNy1hMzhjLTA2Nzg3YjA2NDBhZSJ9LHsiYnVja2V0IjogImNrYW4ubGlpcC5jaCJ9LHsia2V5IjogIjIwMTMtMDItMTlUMjI0MjQwL3NhbXBsZS5jc3YifSx7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovLzE4NS4xNC4xODYuMTE6NTAwMC9zdG9yYWdlL3VwbG9hZC9zdWNjZXNzX2VtcHR5P2xhYmVsPTIwMTMtMDItMTlUMjI0MjQwJTJGc2FtcGxlLmNzdiJ9LFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLCAwLCA1MDAwMDAwMF0seyJ4LWFtei1zdG9yYWdlLWNsYXNzIjogIlNUQU5EQVJEIn1dfQ==', +# 'signature': 'RypkJqVhnpbfqDZlsWBU8vifSzE=', +# 'Content-Type': 'multipart/form-data', +# 'file': 'foobar,something,asdfjh' +# # "image1": open("sample.csv", "r"), +# }) +# request = urllib2.Request(url, datagen, headers) +# print request +# print urllib2.urlopen(request).read() + +# Cleanup +# os.remove(file_name) diff --git a/ckanext/swisstopo/show_dataset.py b/ckanext/swisstopo/show_dataset.py new file mode 100644 index 0000000..cd86f72 --- /dev/null +++ b/ckanext/swisstopo/show_dataset.py @@ -0,0 +1,35 @@ +import ckanclient +import sys +from pprint import pprint + +API_KEY = p.toolkit.asbool(config.get('ckanext.swisstopo.api_key', '')) +BASE_LOCATION = p.toolkit.asbool(config.get('ckanext.swisstopo.base_location', '')) + +ckan = ckanclient.CkanClient(api_key=API_KEY, base_location=BASE_LOCATION) + +package_list = ckan.package_register_get() + +if (len(package_list) <= 0): + print "- No datasets found -" + sys.exit() + +package_list.sort() +for index, package in enumerate(package_list): + print str(index+1) + ") " + package + +try: + selected_dataset = int(raw_input("Select dataset (1-" + str(len(package_list)) + "): ")) + if not selected_dataset in range(1, len(package_list) + 1): + raise ValueError("number is out of range (1-" + str(len(package_list)) + ")") + dataset_name = package_list[selected_dataset-1] +except ValueError as detail: + print "Invalid dataset number: ", detail + sys.exit() + +package_entity = ckan.package_entity_get(dataset_name) + + +max_key_len = len(max(package_entity.keys(), key=len)) +for key, value in package_entity.iteritems(): + print str(key).ljust(max_key_len) + "\t\t" + str(value) + diff --git a/ckanext/swisstopo/swissboundaries.py b/ckanext/swisstopo/swissboundaries.py new file mode 100644 index 0000000..eb8ba62 --- /dev/null +++ b/ckanext/swisstopo/swissboundaries.py @@ -0,0 +1,84 @@ +import ckanclient +import random +import os +import shutil +import tempfile +import zipfile +from pprint import pprint +from collections import defaultdict +import ckan_csw + +API_KEY = p.toolkit.asbool(config.get('ckanext.swisstopo.api_key', '')) +BASE_LOCATION = p.toolkit.asbool(config.get('ckanext.swisstopo.base_location', '')) + +ckan = ckanclient.CkanClient(api_key=API_KEY, base_location=BASE_LOCATION) + +def create_dataset(name, tags, description, metadata): + dataset_name = name + '_' + str(random.randint(1000000, 9999999999)) + dataset_entity = { + 'name': dataset_name, + 'title': name + ' - ' + metadata['title'], + 'tags': tags + ' ' + metadata['tags'], + 'notes': metadata['notes'], + 'url': metadata['url'], + 'author': metadata['author'], + 'author_email': metadata['author_email'], + 'maintainer': metadata['maintainer'], + 'maintainer_email': metadata['maintainer_email'], + 'license': metadata['license'], + } + return dataset_entity + +def extract_file(zipped_file, name, extract_path): + (dirname, filename) = os.path.split(name) + new_path = os.path.join(extract_path, dirname) + extracted_filename = os.path.join(extract_path, name) + if not os.path.exists(new_path): + os.makedirs(new_path) + fd = open(extracted_filename,"w") + fd.write(zipped_file.read(name)) + fd.close() + return extracted_filename + +# Copy the file +origin_file = '/home/www-data/swissBOUNDARIES3D080312.zip' +origin_path, file_name = os.path.split(origin_file) +temp_dir = tempfile.mkdtemp() +shutil.copy(origin_file, temp_dir); +temporary_file = os.path.join(temp_dir, file_name) + +csw = ckan_csw.SwisstopoCkanMetadata(); +metadata = csw.get_ckan_metadata('swissboundaries3D') + +aggregates = defaultdict(list) +# Unzip the file +zipped_file = zipfile.ZipFile(temporary_file) +for name in zipped_file.namelist(): + (dirname, filename) = os.path.split(name) + pure_name, file_extension = os.path.splitext(filename) + dataset_name = pure_name.lower().replace(".","-") + if file_extension not in ['.pdf']: + print "Extracting " + name + extracted_filename = extract_file(zipped_file, name, temp_dir) + resource = { + 'filename': extracted_filename, + 'title': 'swissboundaries3D - ' + filename, + 'description': 'swissboundaries ' + file_extension + ' file', + 'format': file_extension[1:] + } + aggregates[dataset_name].append(resource) + + +for key, aggregate in aggregates.iteritems(): + dataset = create_dataset(key, 'swissboundaries Verwaltungseinheiten', 'swissboundaries ' + key, metadata) + ckan.package_register_post(dataset) + + for resource in aggregate: + pprint(resource) + try: + dataset = ckan.add_package_resource(dataset['name'], resource['filename'], name=resource['title'], resource_type='data', format=resource['format'], description=resource['description']) + except ValueError as e: + print e + pprint(dataset) + +shutil.rmtree(temp_dir); diff --git a/ckanext/swisstopo/tests/__init__.py b/ckanext/swisstopo/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ckanext/swisstopo/tests/ckan_csw_test.py b/ckanext/swisstopo/tests/ckan_csw_test.py new file mode 100644 index 0000000..dc2dc29 --- /dev/null +++ b/ckanext/swisstopo/tests/ckan_csw_test.py @@ -0,0 +1,74 @@ +from mock import Mock +import unittest +from ckanext.swisstopo.ckan_csw import ckan_csw +from ckanext.swisstopo.etree.etree import etree + +class CkanMetadataTest(unittest.TestCase): + def test_init(self): + ckan = ckan_csw.CkanMetadata(url='http://www.geocat.ch/geonetwork/srv/deu/csw?', schema='http://www.geocat.ch/2008/che') + iterator = iter(ckan.metadata) + self.assertEqual(ckan.schema, 'http://www.geocat.ch/2008/che') + + def test_namespaces_available(self): + self.assertEquals(17, len(ckan_csw.namespaces)) + for index, item in ckan_csw.namespaces.iteritems(): + self.assertIsInstance(index, str) + self.assertIsInstance(item, str) + +class SwisstopoCkanMetadataTest(unittest.TestCase): + def setUp(self): + self.test_xml = etree.parse('swissboundaries_csw.test.xml') + self.swisstopo = ckan_csw.SwisstopoCkanMetadata() + self.swisstopo.get_xml = Mock(return_value=self.test_xml) + + def test_get_attribute_license(self): + license = self.swisstopo.get_attribute('swissboundaries3D', 'license') + self.assertIsInstance(license, ckan_csw.StringAttribute) + self.assertEquals(license.get_value(), 'http://www.toposhop.admin.ch/de/shop/terms/use/finished_products') + + def test_get_attribute_maintainer(self): + maintainer = self.swisstopo.get_attribute('swissboundaries3D', 'maintainer') + self.assertIsInstance(maintainer, ckan_csw.CombinedAttribute) + for attr in maintainer._config: + self.assertIsInstance(attr, ckan_csw.XPathTextAttribute) + # self.assertEquals(attr.get_value(self.test_xml), 'test') + # self.assertEquals(maintainer.get_value(self.test_xml, ' '), 'Blubb') + +class AttributeTest(unittest.TestCase): + def test_get_value(self): + attr = ckan_csw.Attribute('config') + self.assertRaises(NotImplementedError, attr.get_value) + +class StringAttributeTest(unittest.TestCase): + def test_get_value(self): + attr = ckan_csw.StringAttribute('my test input') + self.assertEquals('my test input', attr.get_value()) + +class XmlAttributeTest(unittest.TestCase): + def setUp(self): + xml_input = etree.parse('test.xml') + self.test_xml = xml_input.getroot() + + def remove_all_whitespace(self, str): + return ''.join(str.split()) + + def test_xml_attribute_get_value_init(self): + attr = ckan_csw.XmlAttribute('', xml=self.test_xml) + xml_string = open('test.xml', 'r').read() + + xml_string = self.remove_all_whitespace(xml_string) + attr_value = self.remove_all_whitespace(attr.get_value()) + + self.assertEquals(xml_string, attr_value) + + def test_xml_attribute_get_value_call(self): + attr = ckan_csw.XmlAttribute('') + xml_string = open('test.xml', 'r').read() + + xml_string = self.remove_all_whitespace(xml_string) + attr_value = self.remove_all_whitespace(attr.get_value(xml=self.test_xml)) + + self.assertEquals(xml_string, attr_value) + +if __name__ == '__main__': + unittest.main() diff --git a/ckanext/swisstopo/tests/swissboundaries_csw.test.xml b/ckanext/swisstopo/tests/swissboundaries_csw.test.xml new file mode 100644 index 0000000..21ea57b --- /dev/null +++ b/ckanext/swisstopo/tests/swissboundaries_csw.test.xml @@ -0,0 +1,1252 @@ + + + 86cb844f-296b-40cb-b972-5b1ae8028f7c + + + deu + + + + + + + + + + + + + Bundesamt für Landestopografie + + + Office fédéral de topographie + + + Ufficio federale di topografia + + + Federal Office of Topography + + + + + + + Metadaten + + + Métadonnées + + + Metadati + + + Metadata contact + + + + + + + + + +41 31 963 21 11 + + + +41 31 963 24 59 + + + + + + + + + + + + + Wabern + + + 3084 + + + CH + + + metadata@swisstopo.ch + + + Seftigenstrasse + + + 264 + + + + + + + + + http://www.swisstopo.admin.ch + + + + + text/html + + + + + + + + + + + + + + + + + + + 08h30 - 11h00 / 14h00 - 16h00 GMT+1 + + + + + + + + metadata + + + + + swisstopo + + + swisstopo + + + swisstopo + + + swisstopo + + + + + + + 2013-02-26T11:24:25 + + + GM03 2+ + + + + + German + + + UTF8 + + + + + + + French + + + UTF8 + + + + + + + Italian + + + UTF8 + + + + + + + English + + + UTF8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EPSG:21781 + + + + + + + + + + + + + + + EPSG:2056 + + + + + + + + + + + + + + + swissBOUNDARIES3D + + + swissBOUNDARIES3D + + + + + + swissBOUNDARIES3D + + + + + + + swissBOUNDARIES3D + + + swissBOUNDARIES3D + + + + + + swissBOUNDARIES3D + + + + + + + 2013-01-01 + + + + + + + + + + 2013-03-01 + + + + + + + + + + + + 39.3 + + + 39.3 + + + 39.3 + + + + + + + + + Hoheitsgrenzen (Landesvermessung) + + + Limites territoriales (mensuration nationale) + + + + + + Administrative boundaries (national survey) + + + + + + + + + swissBOUNDARIES3D enthält die administrativen Einheiten und Grenzen der Schweiz und des Fürstentums Liechtenstein in vektorieller Form. Das Produkt basiert auf einem optimierten Datenmodell für die Schweiz und ist mit den Daten des Bundesamtes für Statistik abgegelichen. swissBOUNDARIES3D folgt ab 2010 auf den Datensatz GG25. + + + swissBOUNDARIES3D comprend les unités administratives et les frontières de la Suisse et de la Principauté de Liechtenstein en format vectoriel. Il se base sur un modèle de données optimisé pour la Suisse et conforme aux données de l'office fédéral de la statistique. swissBOUNDARIES3D succède dès 2010 au jeu de données GG25. + + + + + + swissBOUNDARIES3D contains all administrative units and national boundaries of Switzerland and the Principality of Liechtenstein in vector form. The product is based on an optimized data model for Switzerland and conforms to the data of the Swiss Federal Statistical Office. swissBOUNDARIES3D replaces the GG25 dataset from 2010 onwards. + + + + + + + + + Bundesamt für Landestopografie + + + Office fédéral de topographie + + + Ufficio federale di topografia + + + Federal Office of Topography + + + + + + + Geodatenabgabe + + + Distribution des géodonnées + + + Distribuzione di geodati + + + Geodata Distribution + + + + + + + + + +41 31 963 21 11 + + + +41 31 963 24 59 + + + + + + + + + + + + + Wabern + + + 3084 + + + CH + + + geodata@swisstopo.ch + + + Seftigenstrasse + + + 264 + + + + + + + + + http://www.swisstopo.ch + + + http://www.swisstopo.ch + + + http://www.swisstopo.ch + + + http://www.swisstopo.ch + + + + + text/html + + + + + + + + + + + + + + + + + + + + + + + + geodata + + + + + swisstopo + + + swisstopo + + + swisstopo + + + swisstopo + + + + + + + + + + + + + + swissBOUNDARIES3D wird jährlich nachgeführt. Die aktuelle Version gibt den Zustand am 1. Januar des laufenden Jahres wieder. Die Nachführung erfolgt auf den Grundlagen der Amtlichen Vermessung (AV) und des Bundesamtes für Statistik (BFS). + + + swissBOUNDARIES3D is updated annually. The current version represents the situation as of 1 January of the current year. Updating is based on the information of the Cadastral Surveying (CS) and the Federal Statistical Office (FSO). + + + swissBOUNDARIES3D viene aggiornato annualmente. La versione attuale rispecchia lo stato al 1° gennaio dell’anno in corso. L’aggiornamento è effettuato sulla base della Misurazione ufficiale (MU) e dei dati dell’Ufficio federale di statistica (UST). + + + swissBOUNDARIES3D est mis à jour annuellement. La version actualisée représente l’état au premier janvier de l’année en cours. Elle est disponible durant le premier trimestre. L’actualisation se base sur les informations de la mensuration officielle (MO) et de l'office fédéral de la statistique (OFS). + + + + + + + + + http://www.swisstopo.admin.ch/internet/swisstopo/de/home/products/landscape.parsys.000101.Image.gif + + + + + + + + + Administrative units + + + Verwaltungseinheiten + + + Unités administratives + + + Unità amministrative + + + + + + + + + + external.theme.inspire-theme + + + + + + + + + + + + national border + + + Landesgrenze + + + frontière nationale + + + confine nazionale + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + Cantonal boundary + + + Kantonsgrenze + + + Limite de canton, limite cantonale + + + confine cantonale + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + Canton + + + Kanton + + + Canton + + + Cantone + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + District boundary + + + Bezirksgrenze + + + Limite de district + + + confine di distretto + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + district + + + Bezirk + + + district + + + distretto + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + Municipal boundary + + + Gemeindegrenze + + + Limite de commune, limite communale + + + confine di comune, confine comunale + + + + + + + local._none_.geocat.ch + + + + + + + + + + + + municipality + + + Gemeinde + + + commune + + + comune + + + + + + + external._none_.gemet + + + + + + + + + + + + + + + + + + + + + + + + + + 10000 + + + + + + + deu + + + fra + + + eng + + + + + + boundaries + + + + + + + Schweiz + + + + + + + + + + + Schweiz + + + + + + + + + + + 1 + + + + + + + + 8.785 47.677 8.796 47.675 8.794 47.68 8.797 47.688 8.8 47.692 8.81 47.693 8.793 47.704 8.769 47.707 8.77 47.715 8.785 47.727 8.799 47.727 8.797 47.735 8.807 47.738 8.809 47.725 8.823 47.716 8.819 47.713 8.826 47.711 8.834 47.715 8.843 47.712 8.848 47.703 8.868 47.705 8.873 47.704 8.876 47.697 8.871 47.693 8.862 47.697 8.852 47.697 8.852 47.681 8.861 47.68 8.868 47.676 8.874 47.667 8.875 47.656 8.875 47.656 8.875 47.655 8.898 47.648 8.941 47.656 8.987 47.676 9.023 47.687 9.1 47.677 9.117 47.669 9.139 47.664 9.15 47.668 9.157 47.666 9.157 47.666 9.163 47.66 9.171 47.655 9.182 47.656 9.182 47.656 9.234 47.657 9.248 47.659 9.268 47.656 9.445 47.595 9.503 47.547 9.515 47.537 9.551 47.537 9.561 47.5 9.561 47.499 9.564 47.493 9.577 47.486 9.594 47.464 9.603 47.462 9.609 47.471 9.622 47.458 9.656 47.454 9.659 47.449 9.651 47.443 9.644 47.435 9.651 47.417 9.652 47.405 9.674 47.391 9.673 47.38 9.658 47.369 9.624 47.366 9.6 47.346 9.587 47.316 9.566 47.304 9.556 47.298 9.543 47.278 9.531 47.271 9.53 47.269 9.521 47.245 9.51 47.232 9.49 47.198 9.488 47.19 9.486 47.181 9.495 47.157 9.503 47.147 9.515 47.122 9.516 47.115 9.52 47.098 9.513 47.085 9.474 47.066 9.472 47.062 9.476 47.052 9.482 47.056 9.486 47.049 9.491 47.056 9.512 47.057 9.531 47.063 9.54 47.065 9.552 47.059 9.557 47.049 9.588 47.055 9.603 47.062 9.607 47.061 9.617 47.054 9.637 47.052 9.645 47.06 9.658 47.058 9.676 47.061 9.718 47.043 9.745 47.041 9.748 47.037 9.783 47.038 9.831 47.014 9.851 47.016 9.861 47.022 9.876 47.021 9.88 47.018 9.871 47.013 9.873 47.007 9.889 47.001 9.891 46.992 9.874 46.966 9.879 46.957 9.876 46.935 9.892 46.932 9.906 46.925 9.912 46.926 9.916 46.922 9.946 46.912 9.959 46.916 9.967 46.912 9.978 46.916 9.981 46.906 9.99 46.902 10.02 46.899 10.052 46.877 10.051 46.865 10.055 46.862 10.088 46.86 10.097 46.849 10.105 46.841 10.118 46.844 10.123 46.848 10.139 46.847 10.147 46.851 10.157 46.848 10.183 46.857 10.194 46.866 10.231 46.866 10.232 46.872 10.235 46.885 10.23 46.898 10.241 46.931 10.257 46.93 10.294 46.922 10.297 46.92 10.302 46.925 10.316 46.925 10.317 46.931 10.306 46.94 10.308 46.948 10.328 46.954 10.33 46.965 10.35 46.991 10.372 46.991 10.389 47.001 10.398 46.997 10.413 46.983 10.427 46.975 10.422 46.96 10.429 46.956 10.434 46.956 10.458 46.951 10.487 46.939 10.486 46.915 10.479 46.908 10.475 46.894 10.465 46.884 10.471 46.873 10.47 46.855 10.467 46.836 10.46 46.835 10.458 46.817 10.451 46.805 10.443 46.799 10.43 46.797 10.427 46.789 10.423 46.788 10.434 46.782 10.442 46.772 10.443 46.754 10.4 46.733 10.418 46.718 10.416 46.709 10.403 46.706 10.393 46.689 10.384 46.683 10.392 46.672 10.391 46.659 10.394 46.655 10.402 46.637 10.409 46.635 10.446 46.641 10.491 46.615 10.484 46.605 10.487 46.589 10.484 46.578 10.475 46.566 10.478 46.557 10.472 46.544 10.459 46.541 10.453 46.531 10.437 46.537 10.418 46.551 10.397 46.544 10.37 46.554 10.352 46.556 10.348 46.549 10.338 46.543 10.325 46.552 10.311 46.547 10.296 46.55 10.289 46.567 10.27 46.578 10.254 46.571 10.246 46.575 10.242 46.592 10.259 46.61 10.245 46.622 10.239 46.635 10.224 46.629 10.215 46.617 10.193 46.623 10.193 46.626 10.129 46.606 10.102 46.611 10.097 46.593 10.101 46.583 10.096 46.577 10.084 46.576 10.081 46.571 10.085 46.567 10.074 46.56 10.062 46.546 10.047 46.544 10.044 46.538 10.054 46.532 10.054 46.523 10.051 46.513 10.042 46.51 10.047 46.498 10.045 46.477 10.052 46.472 10.054 46.465 10.042 46.452 10.039 46.447 10.042 46.443 10.056 46.441 10.06 46.428 10.064 46.426 10.071 46.427 10.081 46.421 10.096 46.422 10.109 46.428 10.128 46.431 10.141 46.428 10.148 46.42 10.161 46.415 10.167 46.407 10.162 46.403 10.162 46.387 10.139 46.384 10.129 46.379 10.129 46.361 10.108 46.351 10.105 46.333 10.117 46.314 10.139 46.305 10.138 46.301 10.156 46.291 10.162 46.282 10.163 46.271 10.172 46.267 10.176 46.258 10.151 46.24 10.146 46.23 10.123 46.224 10.103 46.229 10.09 46.228 10.068 46.218 10.052 46.228 10.049 46.233 10.061 46.248 10.054 46.267 10.029 46.278 9.996 46.285 9.992 46.296 10.001 46.302 10.0 46.313 9.98 46.323 9.994 46.341 9.996 46.351 9.983 46.354 9.964 46.364 9.956 46.374 9.959 46.378 9.953 46.379 9.935 46.375 9.93 46.372 9.931 46.368 9.925 46.366 9.907 46.381 9.868 46.362 9.865 46.365 9.849 46.365 9.832 46.361 9.818 46.35 9.785 46.341 9.778 46.335 9.77 46.336 9.744 46.351 9.737 46.351 9.723 46.341 9.726 46.335 9.717 46.324 9.726 46.32 9.726 46.313 9.718 46.305 9.714 46.293 9.702 46.291 9.689 46.293 9.676 46.303 9.642 46.287 9.622 46.288 9.609 46.294 9.583 46.294 9.561 46.303 9.55 46.302 9.528 46.318 9.517 46.333 9.511 46.337 9.509 46.349 9.494 46.365 9.461 46.376 9.468 46.39 9.462 46.412 9.456 46.416 9.454 46.421 9.461 46.442 9.459 46.463 9.466 46.47 9.462 46.48 9.45 46.48 9.449 46.484 9.461 46.485 9.461 46.506 9.464 46.508 9.459 46.508 9.434 46.498 9.425 46.489 9.424 46.476 9.412 46.467 9.39 46.473 9.385 46.482 9.371 46.49 9.369 46.496 9.373 46.504 9.362 46.51 9.355 46.504 9.339 46.504 9.337 46.506 9.311 46.504 9.283 46.497 9.277 46.485 9.274 46.457 9.265 46.451 9.247 46.447 9.25 46.431 9.264 46.421 9.275 46.419 9.28 46.413 9.282 46.402 9.276 46.395 9.284 46.385 9.276 46.368 9.287 46.357 9.296 46.355 9.299 46.344 9.292 46.336 9.297 46.328 9.295 46.318 9.285 46.314 9.285 46.297 9.272 46.29 9.268 46.282 9.259 46.278 9.257 46.269 9.25 46.266 9.253 46.262 9.248 46.247 9.247 46.232 9.221 46.229 9.214 46.211 9.202 46.208 9.195 46.194 9.198 46.187 9.195 46.179 9.185 46.172 9.173 46.171 9.169 46.172 9.159 46.17 9.157 46.162 9.145 46.158 9.129 46.147 9.121 46.135 9.112 46.135 9.079 46.121 9.072 46.118 9.08 46.105 9.09 46.087 9.082 46.077 9.078 46.069 9.074 46.062 9.05 46.062 9.021 46.052 9.016 46.047 9.008 46.03 9.023 46.017 9.023 46.017 9.025 46.001 9.025 46.001 9.028 45.994 8.991 45.972 8.989 45.973 8.989 45.97 8.994 45.966 9.014 45.961 9.017 45.949 9.012 45.944 9.021 45.935 9.019 45.928 9.03 45.927 9.043 45.928 9.048 45.923 9.06 45.921 9.059 45.917 9.076 45.912 9.077 45.899 9.087 45.902 9.089 45.897 9.085 45.896 9.072 45.882 9.065 45.876 9.055 45.874 9.049 45.863 9.051 45.856 9.035 45.84 9.038 45.836 9.031 45.825 9.018 45.818 8.994 45.822 8.997 45.835 8.987 45.839 8.971 45.833 8.956 45.842 8.947 45.843 8.912 45.83 8.914 45.842 8.932 45.861 8.939 45.864 8.945 45.867 8.943 45.869 8.937 45.867 8.935 45.87 8.927 45.892 8.92 45.909 8.917 45.914 8.917 45.914 8.914 45.918 8.908 45.918 8.896 45.927 8.893 45.932 8.893 45.937 8.897 45.942 8.897 45.955 8.894 45.959 8.878 45.957 8.868 45.961 8.859 45.967 8.859 45.967 8.854 45.971 8.839 45.984 8.832 45.988 8.824 45.988 8.794 45.992 8.791 45.989 8.786 45.989 8.793 46.008 8.797 46.012 8.806 46.022 8.82 46.026 8.828 46.034 8.83 46.042 8.833 46.041 8.835 46.044 8.828 46.047 8.834 46.051 8.844 46.048 8.855 46.062 8.852 46.076 8.835 46.082 8.806 46.101 8.802 46.097 8.8 46.095 8.783 46.094 8.756 46.105 8.756 46.105 8.742 46.122 8.724 46.11 8.714 46.097 8.697 46.102 8.697 46.102 8.686 46.103 8.681 46.108 8.658 46.113 8.648 46.123 8.612 46.122 8.61 46.132 8.593 46.145 8.604 46.154 8.574 46.164 8.57 46.177 8.555 46.187 8.553 46.192 8.541 46.197 8.533 46.218 8.469 46.233 8.464 46.245 8.447 46.248 8.443 46.252 8.445 46.257 8.456 46.264 8.428 46.298 8.441 46.304 8.444 46.319 8.454 46.323 8.464 46.333 8.464 46.344 8.462 46.354 8.468 46.364 8.466 46.38 8.461 46.387 8.471 46.396 8.464 46.403 8.468 46.412 8.457 46.423 8.462 46.451 8.453 46.455 8.45 46.462 8.438 46.464 8.407 46.458 8.393 46.452 8.385 46.452 8.367 46.452 8.326 46.427 8.314 46.424 8.308 46.426 8.299 46.414 8.289 46.409 8.316 46.399 8.318 46.387 8.313 46.377 8.286 46.366 8.264 46.365 8.261 46.361 8.266 46.352 8.263 46.346 8.236 46.34 8.224 46.334 8.223 46.327 8.215 46.32 8.212 46.31 8.206 46.306 8.179 46.298 8.161 46.296 8.141 46.302 8.121 46.292 8.113 46.281 8.081 46.261 8.088 46.254 8.1 46.252 8.102 46.25 8.11 46.25 8.116 46.236 8.127 46.228 8.139 46.226 8.153 46.191 8.165 46.182 8.165 46.177 8.15 46.161 8.155 46.148 8.144 46.137 8.127 46.136 8.116 46.13 8.114 46.117 8.108 46.112 8.081 46.105 8.072 46.106 8.043 46.1 8.035 46.101 8.022 46.07 8.034 46.044 8.013 46.031 8.018 46.025 8.012 46.012 8.001 46.012 7.989 45.996 7.981 45.998 7.909 45.997 7.894 45.981 7.878 45.973 7.881 45.968 7.877 45.949 7.871 45.947 7.868 45.937 7.877 45.927 7.873 45.921 7.864 45.917 7.822 45.927 7.8 45.917 7.769 45.937 7.75 45.94 7.735 45.924 7.72 45.924 7.708 45.935 7.71 45.948 7.699 45.954 7.681 45.957 7.665 45.975 7.657 45.977 7.639 45.97 7.587 45.971 7.581 45.975 7.575 45.987 7.546 45.984 7.542 45.976 7.546 45.962 7.538 45.955 7.511 45.959 7.488 45.956 7.472 45.948 7.475 45.937 7.472 45.934 7.459 45.936 7.445 45.932 7.427 45.915 7.412 45.909 7.406 45.909 7.383 45.897 7.367 45.904 7.361 45.903 7.356 45.91 7.345 45.915 7.324 45.91 7.294 45.922 7.286 45.916 7.274 45.9 7.257 45.888 7.229 45.892 7.216 45.889 7.2 45.873 7.201 45.863 7.197 45.861 7.191 45.859 7.175 45.863 7.162 45.871 7.164 45.876 7.154 45.879 7.135 45.873 7.132 45.867 7.118 45.859 7.101 45.86 7.095 45.876 7.064 45.9 7.061 45.913 7.044 45.923 7.036 45.938 7.037 45.955 7.021 45.959 7.009 45.969 7.011 45.973 7.022 45.977 7.022 45.981 7.013 45.987 7.011 45.997 7.006 46.001 7.001 45.999 6.985 46.004 6.981 46.019 6.963 46.03 6.949 46.051 6.944 46.051 6.936 46.055 6.937 46.064 6.925 46.065 6.909 46.05 6.9 46.049 6.89 46.042 6.883 46.045 6.876 46.048 6.873 46.055 6.88 46.069 6.891 46.074 6.886 46.097 6.895 46.108 6.893 46.114 6.9 46.124 6.852 46.126 6.843 46.129 6.842 46.132 6.814 46.13 6.798 46.137 6.79 46.154 6.792 46.163 6.813 46.182 6.807 46.196 6.804 46.205 6.822 46.223 6.821 46.23 6.833 46.236 6.843 46.249 6.854 46.254 6.855 46.259 6.86 46.266 6.859 46.274 6.863 46.278 6.859 46.29 6.855 46.293 6.847 46.29 6.83 46.3 6.829 46.306 6.82 46.316 6.801 46.32 6.794 46.333 6.784 46.337 6.775 46.347 6.772 46.361 6.781 46.367 6.793 46.367 6.804 46.377 6.806 46.383 6.802 46.388 6.805 46.394 6.805 46.394 6.821 46.427 6.682 46.454 6.519 46.456 6.426 46.416 6.335 46.404 6.253 46.36 6.241 46.344 6.232 46.331 6.22 46.312 6.242 46.304 6.242 46.304 6.246 46.303 6.253 46.291 6.244 46.285 6.238 46.276 6.25 46.263 6.25 46.262 6.267 46.248 6.284 46.254 6.29 46.26 6.296 46.256 6.306 46.256 6.31 46.244 6.291 46.224 6.277 46.216 6.249 46.206 6.245 46.207 6.245 46.205 6.234 46.206 6.224 46.201 6.186 46.178 6.189 46.166 6.175 46.158 6.154 46.152 6.146 46.147 6.136 46.142 6.125 46.141 6.1 46.144 6.092 46.152 6.074 46.149 6.052 46.151 6.037 46.137 6.024 46.141 5.994 46.145 5.982 46.142 5.977 46.133 5.957 46.129 5.956 46.132 5.966 46.138 5.964 46.145 5.976 46.161 5.981 46.17 5.992 46.177 5.995 46.182 5.992 46.187 5.964 46.197 5.975 46.215 5.993 46.223 6.0 46.22 6.016 46.232 6.034 46.239 6.046 46.231 6.063 46.246 6.07 46.241 6.088 46.246 6.102 46.238 6.124 46.251 6.12 46.261 6.12 46.265 6.104 46.278 6.103 46.285 6.121 46.297 6.12 46.312 6.126 46.317 6.132 46.325 6.139 46.335 6.138 46.339 6.149 46.343 6.158 46.351 6.159 46.357 6.17 46.366 6.159 46.38 6.15 46.377 6.113 46.4 6.106 46.399 6.098 46.409 6.064 46.416 6.075 46.432 6.084 46.44 6.086 46.444 6.074 46.454 6.077 46.458 6.073 46.465 6.097 46.481 6.113 46.51 6.138 46.531 6.144 46.528 6.154 46.537 6.149 46.539 6.157 46.545 6.111 46.576 6.14 46.598 6.161 46.61 6.179 46.616 6.186 46.624 6.219 46.645 6.267 46.676 6.269 46.683 6.282 46.691 6.307 46.699 6.341 46.71 6.36 46.723 6.372 46.724 6.385 46.732 6.392 46.739 6.388 46.743 6.395 46.748 6.417 46.753 6.438 46.762 6.439 46.767 6.452 46.774 6.458 46.789 6.435 46.802 6.431 46.812 6.441 46.816 6.443 46.833 6.46 46.851 6.463 46.876 6.463 46.893 6.433 46.929 6.45 46.936 6.471 46.956 6.486 46.967 6.496 46.974 6.505 46.966 6.572 46.982 6.591 46.991 6.618 46.992 6.634 46.998 6.659 47.027 6.676 47.035 6.699 47.039 6.719 47.052 6.701 47.059 6.692 47.068 6.701 47.07 6.708 47.083 6.715 47.088 6.725 47.091 6.736 47.09 6.744 47.092 6.747 47.097 6.741 47.11 6.764 47.12 6.792 47.127 6.816 47.136 6.85 47.156 6.858 47.165 6.844 47.166 6.841 47.171 6.871 47.185 6.88 47.201 6.89 47.205 6.943 47.235 6.943 47.238 6.956 47.244 6.948 47.256 6.951 47.271 6.941 47.286 6.951 47.292 6.97 47.292 7.008 47.301 7.016 47.315 7.013 47.32 7.009 47.32 7.01 47.325 7.035 47.328 7.046 47.326 7.057 47.334 7.062 47.344 7.056 47.347 7.05 47.361 7.043 47.364 7.035 47.363 7.034 47.368 7.012 47.373 6.995 47.363 6.924 47.355 6.903 47.36 6.88 47.353 6.884 47.373 6.895 47.382 6.905 47.383 6.913 47.388 6.909 47.396 6.918 47.403 6.938 47.406 6.94 47.433 6.964 47.436 6.97 47.447 6.996 47.45 7.002 47.454 6.997 47.456 7.001 47.462 7.0 47.467 6.992 47.466 6.986 47.476 6.988 47.495 7.02 47.504 7.037 47.498 7.061 47.495 7.072 47.492 7.075 47.488 7.094 47.495 7.112 47.495 7.128 47.504 7.15 47.497 7.159 47.491 7.171 47.489 7.201 47.494 7.203 47.491 7.191 47.487 7.179 47.464 7.17 47.443 7.193 47.439 7.196 47.435 7.207 47.435 7.226 47.44 7.233 47.439 7.246 47.427 7.245 47.421 7.282 47.435 7.327 47.44 7.331 47.442 7.353 47.434 7.381 47.432 7.421 47.446 7.431 47.459 7.446 47.462 7.456 47.471 7.456 47.473 7.429 47.483 7.421 47.481 7.433 47.497 7.462 47.489 7.471 47.481 7.487 47.482 7.498 47.489 7.51 47.503 7.509 47.509 7.499 47.516 7.498 47.521 7.503 47.516 7.524 47.515 7.531 47.527 7.527 47.533 7.516 47.533 7.508 47.528 7.501 47.529 7.498 47.536 7.504 47.543 7.518 47.546 7.555 47.564 7.559 47.569 7.557 47.573 7.566 47.578 7.585 47.576 7.589 47.59 7.605 47.585 7.605 47.578 7.619 47.577 7.625 47.579 7.646 47.597 7.674 47.592 7.683 47.598 7.693 47.601 7.672 47.587 7.681 47.581 7.69 47.571 7.686 47.566 7.683 47.57 7.653 47.562 7.648 47.56 7.636 47.564 7.634 47.561 7.646 47.552 7.651 47.547 7.661 47.545 7.666 47.538 7.675 47.534 7.686 47.533 7.697 47.533 7.714 47.54 7.753 47.545 7.758 47.549 7.796 47.557 7.812 47.569 7.82 47.587 7.832 47.587 7.837 47.583 7.846 47.582 7.869 47.589 7.887 47.588 7.898 47.584 7.911 47.57 7.909 47.555 7.918 47.547 7.94 47.545 7.949 47.545 7.956 47.557 7.965 47.557 8.008 47.555 8.008 47.555 8.022 47.55 8.046 47.555 8.067 47.565 8.075 47.562 8.085 47.557 8.097 47.561 8.107 47.58 8.113 47.584 8.126 47.583 8.137 47.584 8.138 47.59 8.148 47.596 8.159 47.594 8.185 47.605 8.194 47.616 8.202 47.62 8.214 47.62 8.222 47.616 8.224 47.607 8.228 47.605 8.255 47.615 8.261 47.614 8.265 47.609 8.279 47.612 8.289 47.61 8.298 47.606 8.297 47.59 8.316 47.579 8.324 47.573 8.337 47.57 8.362 47.569 8.378 47.567 8.392 47.575 8.4 47.577 8.416 47.571 8.426 47.568 8.434 47.567 8.464 47.572 8.477 47.578 8.484 47.577 8.487 47.578 8.495 47.581 8.487 47.587 8.468 47.584 8.46 47.588 8.458 47.597 8.461 47.602 8.478 47.611 8.479 47.613 8.507 47.618 8.515 47.623 8.517 47.632 8.521 47.634 8.539 47.631 8.539 47.628 8.558 47.624 8.569 47.617 8.572 47.611 8.563 47.599 8.583 47.596 8.593 47.606 8.596 47.606 8.603 47.611 8.605 47.616 8.598 47.627 8.596 47.643 8.607 47.653 8.614 47.645 8.603 47.639 8.607 47.637 8.616 47.638 8.623 47.641 8.628 47.648 8.628 47.654 8.615 47.662 8.609 47.663 8.606 47.669 8.607 47.672 8.598 47.673 8.593 47.667 8.578 47.662 8.565 47.665 8.564 47.67 8.547 47.668 8.54 47.662 8.527 47.66 8.534 47.65 8.532 47.646 8.5 47.647 8.494 47.647 8.492 47.642 8.483 47.644 8.476 47.65 8.473 47.648 8.478 47.64 8.474 47.638 8.466 47.642 8.464 47.656 8.449 47.655 8.445 47.654 8.424 47.667 8.412 47.666 8.406 47.675 8.421 47.684 8.412 47.694 8.406 47.696 8.408 47.702 8.417 47.71 8.426 47.711 8.445 47.723 8.455 47.722 8.457 47.729 8.453 47.731 8.45 47.739 8.473 47.764 8.489 47.773 8.496 47.771 8.51 47.776 8.52 47.77 8.526 47.778 8.553 47.785 8.566 47.778 8.577 47.782 8.574 47.787 8.562 47.793 8.562 47.802 8.568 47.808 8.576 47.802 8.614 47.801 8.622 47.795 8.62 47.789 8.616 47.787 8.618 47.78 8.623 47.777 8.619 47.768 8.628 47.759 8.634 47.76 8.645 47.765 8.653 47.773 8.645 47.787 8.647 47.794 8.657 47.8 8.668 47.788 8.68 47.785 8.689 47.758 8.695 47.756 8.714 47.765 8.727 47.762 8.741 47.752 8.741 47.748 8.724 47.746 8.715 47.739 8.712 47.731 8.718 47.722 8.736 47.716 8.728 47.702 8.728 47.693 8.758 47.689 8.785 47.677 + + + + + + + + + + + + 1 + + + + 5.956 + + + 10.491 + + + 45.818 + + + 47.808 + + + + + + + + + + + Liechtenstein + + + + + + + + + + + Liechtenstein + + + + + + + + + + + 1 + + + + + + + + 9.536 47.266 9.537 47.266 9.537 47.266 9.538 47.266 9.538 47.266 9.539 47.266 9.539 47.266 9.539 47.266 9.54 47.265 9.54 47.265 9.54 47.265 9.54 47.265 9.54 47.264 9.54 47.264 9.54 47.263 9.54 47.263 9.54 47.263 9.54 47.262 9.539 47.262 9.539 47.262 9.539 47.262 9.54 47.262 9.54 47.261 9.54 47.261 9.543 47.26 9.543 47.259 9.544 47.259 9.544 47.259 9.544 47.258 9.545 47.258 9.546 47.258 9.548 47.257 9.549 47.257 9.55 47.256 9.551 47.256 9.552 47.255 9.552 47.255 9.552 47.255 9.552 47.255 9.553 47.254 9.553 47.254 9.553 47.254 9.554 47.253 9.554 47.253 9.554 47.253 9.555 47.253 9.556 47.253 9.556 47.253 9.557 47.252 9.557 47.251 9.558 47.251 9.56 47.251 9.56 47.25 9.561 47.249 9.561 47.249 9.561 47.249 9.562 47.249 9.562 47.248 9.562 47.248 9.562 47.247 9.563 47.246 9.564 47.246 9.567 47.243 9.567 47.242 9.567 47.241 9.567 47.241 9.566 47.24 9.566 47.239 9.566 47.239 9.565 47.238 9.564 47.237 9.562 47.237 9.562 47.236 9.561 47.235 9.561 47.235 9.56 47.235 9.56 47.234 9.56 47.234 9.559 47.233 9.558 47.233 9.558 47.232 9.558 47.231 9.557 47.231 9.557 47.23 9.556 47.23 9.556 47.229 9.555 47.229 9.555 47.229 9.554 47.227 9.554 47.227 9.555 47.227 9.553 47.226 9.553 47.225 9.553 47.225 9.552 47.225 9.553 47.225 9.552 47.224 9.552 47.224 9.552 47.224 9.553 47.224 9.554 47.224 9.555 47.224 9.555 47.224 9.555 47.223 9.555 47.223 9.556 47.223 9.557 47.223 9.557 47.223 9.557 47.223 9.558 47.224 9.559 47.224 9.559 47.224 9.559 47.224 9.56 47.224 9.56 47.224 9.561 47.223 9.562 47.223 9.563 47.222 9.563 47.222 9.563 47.221 9.564 47.221 9.564 47.221 9.564 47.221 9.565 47.221 9.566 47.22 9.566 47.22 9.567 47.22 9.567 47.22 9.567 47.22 9.567 47.22 9.568 47.22 9.569 47.22 9.569 47.219 9.569 47.219 9.57 47.218 9.571 47.218 9.571 47.217 9.572 47.216 9.573 47.216 9.573 47.215 9.574 47.215 9.576 47.214 9.577 47.212 9.577 47.212 9.577 47.211 9.577 47.211 9.578 47.21 9.578 47.209 9.579 47.209 9.58 47.208 9.581 47.208 9.582 47.207 9.582 47.206 9.584 47.206 9.585 47.205 9.585 47.205 9.585 47.205 9.583 47.203 9.583 47.203 9.582 47.202 9.582 47.201 9.582 47.201 9.581 47.2 9.581 47.199 9.581 47.198 9.58 47.197 9.58 47.196 9.58 47.196 9.579 47.196 9.579 47.195 9.579 47.195 9.577 47.194 9.577 47.193 9.576 47.193 9.576 47.193 9.574 47.191 9.574 47.191 9.573 47.191 9.573 47.188 9.573 47.187 9.574 47.186 9.574 47.185 9.573 47.184 9.573 47.184 9.574 47.183 9.574 47.182 9.574 47.18 9.574 47.179 9.574 47.179 9.574 47.178 9.574 47.178 9.573 47.177 9.574 47.177 9.573 47.177 9.574 47.177 9.573 47.176 9.573 47.176 9.572 47.175 9.571 47.175 9.571 47.175 9.57 47.175 9.568 47.174 9.568 47.173 9.567 47.173 9.566 47.172 9.566 47.172 9.566 47.172 9.565 47.171 9.565 47.171 9.565 47.17 9.565 47.17 9.566 47.17 9.567 47.17 9.568 47.17 9.569 47.17 9.569 47.17 9.57 47.17 9.571 47.17 9.573 47.17 9.575 47.17 9.576 47.17 9.577 47.171 9.578 47.171 9.579 47.171 9.582 47.169 9.584 47.168 9.589 47.166 9.591 47.165 9.591 47.165 9.592 47.164 9.597 47.163 9.598 47.162 9.599 47.161 9.601 47.159 9.601 47.159 9.601 47.158 9.601 47.158 9.6 47.157 9.6 47.157 9.6 47.157 9.601 47.156 9.601 47.156 9.601 47.156 9.602 47.156 9.602 47.156 9.602 47.155 9.603 47.154 9.603 47.154 9.603 47.154 9.603 47.153 9.603 47.153 9.603 47.153 9.603 47.152 9.603 47.152 9.603 47.152 9.603 47.151 9.605 47.15 9.605 47.149 9.606 47.149 9.608 47.148 9.608 47.148 9.609 47.148 9.61 47.148 9.611 47.147 9.612 47.147 9.614 47.148 9.614 47.148 9.615 47.148 9.617 47.149 9.618 47.149 9.618 47.15 9.619 47.15 9.619 47.15 9.619 47.15 9.619 47.151 9.62 47.151 9.62 47.152 9.621 47.152 9.622 47.151 9.621 47.151 9.621 47.15 9.622 47.15 9.622 47.15 9.623 47.149 9.623 47.148 9.623 47.148 9.623 47.148 9.623 47.147 9.623 47.147 9.624 47.147 9.624 47.147 9.624 47.146 9.624 47.146 9.625 47.146 9.626 47.146 9.624 47.143 9.623 47.143 9.623 47.142 9.623 47.142 9.623 47.141 9.623 47.141 9.623 47.141 9.625 47.139 9.625 47.138 9.625 47.138 9.625 47.138 9.624 47.136 9.624 47.135 9.624 47.135 9.625 47.134 9.625 47.134 9.625 47.134 9.625 47.133 9.625 47.132 9.626 47.132 9.626 47.131 9.628 47.131 9.628 47.131 9.629 47.131 9.63 47.131 9.63 47.13 9.631 47.13 9.631 47.129 9.632 47.129 9.633 47.129 9.634 47.128 9.635 47.128 9.635 47.128 9.634 47.127 9.633 47.127 9.633 47.125 9.633 47.125 9.632 47.124 9.631 47.124 9.63 47.123 9.628 47.122 9.628 47.121 9.627 47.121 9.627 47.121 9.626 47.12 9.626 47.12 9.626 47.119 9.625 47.119 9.625 47.119 9.625 47.118 9.625 47.118 9.625 47.117 9.625 47.116 9.625 47.116 9.625 47.115 9.624 47.114 9.624 47.114 9.624 47.113 9.624 47.113 9.624 47.113 9.623 47.113 9.623 47.112 9.621 47.111 9.621 47.111 9.621 47.111 9.621 47.11 9.622 47.109 9.622 47.108 9.623 47.108 9.625 47.108 9.626 47.108 9.626 47.108 9.627 47.108 9.628 47.108 9.629 47.108 9.628 47.107 9.628 47.106 9.629 47.105 9.63 47.105 9.631 47.104 9.632 47.103 9.632 47.103 9.633 47.103 9.633 47.102 9.634 47.102 9.634 47.101 9.634 47.101 9.634 47.101 9.635 47.1 9.635 47.099 9.636 47.097 9.636 47.096 9.636 47.095 9.636 47.093 9.635 47.092 9.635 47.091 9.633 47.086 9.633 47.085 9.633 47.085 9.633 47.083 9.633 47.083 9.629 47.083 9.626 47.083 9.623 47.083 9.623 47.082 9.621 47.08 9.621 47.08 9.621 47.08 9.621 47.08 9.619 47.078 9.618 47.078 9.617 47.079 9.616 47.079 9.615 47.079 9.615 47.079 9.614 47.079 9.614 47.079 9.613 47.079 9.613 47.079 9.612 47.079 9.612 47.079 9.612 47.079 9.611 47.079 9.611 47.078 9.612 47.078 9.611 47.077 9.611 47.077 9.611 47.077 9.611 47.076 9.611 47.076 9.611 47.075 9.61 47.075 9.611 47.075 9.611 47.075 9.611 47.074 9.612 47.074 9.612 47.074 9.612 47.073 9.612 47.073 9.613 47.073 9.613 47.072 9.613 47.071 9.613 47.07 9.613 47.069 9.613 47.068 9.613 47.068 9.612 47.068 9.611 47.067 9.611 47.067 9.611 47.066 9.611 47.066 9.611 47.066 9.611 47.065 9.612 47.065 9.612 47.065 9.612 47.064 9.611 47.064 9.611 47.064 9.611 47.064 9.61 47.063 9.61 47.063 9.61 47.063 9.609 47.062 9.609 47.062 9.607 47.061 9.607 47.061 9.607 47.061 9.606 47.061 9.605 47.061 9.605 47.061 9.605 47.061 9.604 47.062 9.604 47.062 9.603 47.062 9.603 47.062 9.603 47.061 9.602 47.061 9.602 47.061 9.602 47.061 9.602 47.061 9.601 47.061 9.601 47.06 9.601 47.06 9.601 47.06 9.601 47.06 9.6 47.06 9.6 47.059 9.598 47.059 9.598 47.059 9.598 47.059 9.597 47.059 9.597 47.059 9.597 47.059 9.596 47.058 9.595 47.058 9.595 47.058 9.595 47.058 9.594 47.057 9.594 47.057 9.594 47.057 9.593 47.057 9.593 47.057 9.592 47.057 9.592 47.057 9.591 47.057 9.591 47.057 9.591 47.057 9.59 47.056 9.59 47.056 9.589 47.056 9.589 47.056 9.589 47.056 9.589 47.056 9.589 47.055 9.589 47.055 9.589 47.055 9.589 47.055 9.588 47.055 9.588 47.055 9.588 47.055 9.588 47.055 9.587 47.055 9.587 47.055 9.586 47.054 9.585 47.054 9.585 47.054 9.584 47.054 9.583 47.054 9.583 47.053 9.582 47.053 9.582 47.053 9.582 47.053 9.582 47.053 9.582 47.053 9.581 47.053 9.581 47.053 9.581 47.053 9.58 47.053 9.579 47.053 9.579 47.053 9.579 47.053 9.578 47.053 9.578 47.053 9.578 47.053 9.578 47.053 9.578 47.053 9.577 47.053 9.577 47.053 9.576 47.053 9.576 47.053 9.575 47.053 9.575 47.053 9.574 47.053 9.573 47.053 9.573 47.053 9.572 47.052 9.572 47.052 9.572 47.052 9.571 47.052 9.571 47.052 9.571 47.052 9.57 47.052 9.569 47.052 9.569 47.052 9.568 47.052 9.567 47.051 9.566 47.051 9.565 47.051 9.565 47.051 9.564 47.051 9.564 47.051 9.564 47.05 9.564 47.05 9.563 47.05 9.563 47.05 9.562 47.049 9.561 47.049 9.561 47.049 9.561 47.049 9.561 47.049 9.56 47.049 9.56 47.049 9.559 47.048 9.558 47.048 9.557 47.049 9.557 47.049 9.556 47.049 9.556 47.05 9.556 47.05 9.556 47.05 9.556 47.05 9.555 47.05 9.555 47.05 9.555 47.05 9.555 47.05 9.554 47.05 9.554 47.051 9.554 47.051 9.554 47.051 9.554 47.051 9.554 47.051 9.554 47.052 9.554 47.052 9.554 47.052 9.554 47.052 9.553 47.053 9.554 47.053 9.554 47.053 9.553 47.054 9.553 47.055 9.553 47.057 9.553 47.057 9.553 47.057 9.552 47.058 9.552 47.058 9.552 47.058 9.552 47.059 9.552 47.059 9.551 47.059 9.551 47.059 9.551 47.059 9.55 47.06 9.55 47.06 9.55 47.06 9.549 47.061 9.549 47.061 9.549 47.061 9.548 47.061 9.548 47.061 9.548 47.061 9.548 47.062 9.547 47.062 9.547 47.062 9.546 47.062 9.545 47.062 9.545 47.062 9.545 47.062 9.544 47.063 9.544 47.063 9.544 47.063 9.544 47.063 9.544 47.063 9.544 47.063 9.543 47.064 9.543 47.064 9.543 47.064 9.542 47.064 9.542 47.064 9.541 47.064 9.541 47.064 9.541 47.064 9.54 47.065 9.54 47.065 9.538 47.065 9.538 47.065 9.537 47.065 9.537 47.065 9.536 47.064 9.536 47.064 9.536 47.064 9.535 47.064 9.535 47.064 9.535 47.064 9.535 47.064 9.534 47.064 9.534 47.064 9.533 47.063 9.532 47.063 9.532 47.063 9.532 47.063 9.532 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.531 47.063 9.521 47.061 9.517 47.06 9.516 47.06 9.515 47.059 9.515 47.058 9.514 47.057 9.512 47.057 9.503 47.056 9.502 47.057 9.501 47.057 9.5 47.057 9.5 47.056 9.499 47.055 9.5 47.054 9.497 47.054 9.495 47.056 9.493 47.057 9.492 47.056 9.491 47.056 9.491 47.056 9.49 47.055 9.49 47.054 9.488 47.053 9.486 47.05 9.486 47.049 9.484 47.049 9.483 47.051 9.483 47.052 9.482 47.053 9.482 47.053 9.482 47.055 9.482 47.056 9.481 47.056 9.48 47.055 9.48 47.055 9.479 47.056 9.477 47.055 9.476 47.053 9.477 47.052 9.477 47.052 9.476 47.052 9.472 47.06 9.472 47.062 9.472 47.063 9.472 47.063 9.472 47.064 9.472 47.065 9.473 47.066 9.474 47.066 9.475 47.067 9.475 47.067 9.476 47.067 9.477 47.068 9.479 47.069 9.482 47.07 9.488 47.072 9.491 47.073 9.493 47.074 9.494 47.075 9.499 47.078 9.505 47.081 9.508 47.083 9.511 47.084 9.513 47.085 9.514 47.086 9.514 47.086 9.515 47.087 9.516 47.088 9.516 47.089 9.518 47.093 9.518 47.094 9.519 47.095 9.519 47.097 9.52 47.098 9.52 47.1 9.519 47.102 9.519 47.104 9.519 47.106 9.518 47.107 9.516 47.115 9.516 47.116 9.515 47.122 9.514 47.126 9.512 47.13 9.512 47.132 9.512 47.132 9.511 47.134 9.51 47.136 9.51 47.137 9.509 47.14 9.508 47.141 9.507 47.142 9.506 47.144 9.503 47.147 9.501 47.148 9.5 47.15 9.499 47.151 9.497 47.154 9.495 47.157 9.494 47.159 9.492 47.162 9.491 47.163 9.491 47.165 9.49 47.166 9.49 47.166 9.489 47.169 9.489 47.171 9.488 47.173 9.488 47.174 9.488 47.175 9.487 47.177 9.487 47.178 9.486 47.179 9.486 47.181 9.486 47.183 9.486 47.183 9.487 47.186 9.487 47.186 9.487 47.188 9.488 47.19 9.488 47.191 9.489 47.193 9.489 47.194 9.49 47.196 9.49 47.196 9.49 47.198 9.49 47.198 9.491 47.199 9.492 47.2 9.493 47.202 9.494 47.203 9.494 47.204 9.496 47.206 9.497 47.207 9.499 47.21 9.5 47.211 9.5 47.212 9.502 47.22 9.504 47.224 9.51 47.232 9.511 47.232 9.52 47.243 9.521 47.245 9.53 47.263 9.53 47.263 9.53 47.269 9.53 47.269 9.53 47.27 9.531 47.271 9.532 47.269 9.533 47.268 9.534 47.268 9.534 47.268 9.534 47.268 9.536 47.266 + + + + + + + + + + + + 1 + + + + 9.472 + + + 9.636 + + + 47.048 + + + 47.271 + + + + + + + 39.3 + + + + + + + + + + 0 + + + + + + + swissBOUNDARIES3D Grenzen Schweizweit in 3D + + + swissBOUNDARIES3D Les limites administrative de la Suisse en 3D + + + + + + + 2010-10-01 + + + + + + + + + + http://www.swisstopo.admin.ch/internet/swisstopo/de/home/products/landscape/swissBOUNDARIES3D.parsysrelated1.18958.downloadList.96046.DownloadFile.tmp/201010sboundinfod.pdf + + + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/products/landscape/swissBOUNDARIES3D.parsysrelated1.22532.downloadList.36650.DownloadFile.tmp/201010sboundinfof.pdf + + + + + + + + + + + + + + + + ESRI Shapefile + + + - + + + + + + + ESRI File Geodatabase + + + - + + + + + + + DXF + + + - + + + + + + + INTERLIS + + + 1 + + + + + + + INTERLIS + + + 2 + + + + + + + + + + + http://www.swisstopo.admin.ch/internet/swisstopo/de/home/products/landscape/swissBOUNDARIES3D.html + + + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/products/landscape/swissBOUNDARIES3D.html + + + http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/landscape/swissBOUNDARIES3D.html + + + + + WWW:LINK-1.0-http--link + + + + + Produkthomepage + + + + + + + + + + + + + + + + + + http://www.toposhop.admin.ch/de/shop/products/landscape/swissBoundaries3D_1 + + + http://www.toposhop.admin.ch/fr/shop/products/landscape/swissBoundaries3D_1 + + + http://www.toposhop.admin.ch/en/shop/products/landscape/swissBoundaries3D_1 + + + + + WWW:LINK-1.0-http--link + + + + + Toposhop + + + + + + + + + + + + + + + + + + - + + + + + WWW:LINK-1.0-http--link + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + 510.620 + + + + + + + Verordnung über Geoinformation + + + Ordonnance sur la géoinformation : Annexe 1, Catalogue des géodonnées de base relevant du droit fédéral + + + Ordinanza sulla geoinformazione : Allegato 1, Catalogo dei geodati di base del diritto federale + + + + + + + Geoinformationsverordnung GeoIV + + + OGéo + + + OGI + + + + + + + 2008-05-21 + + + + + + + + + + 2008-07-01 + + + + + + + + + + Im Anhang 1 werden alle Geodaten aufgelistet, welche über ein gesetzliche Grundlage auf Bundesebene verfügen. + + + Dans l'annexe 1 sont listées toutes les géodonnées de base de droit fédéral + + + Questo elenco contiene tutti i geodati di base del diritto federale + + + + + + + + + 89359 + iso19139.che + 2011-01-24T14:02:02 + 2013-02-26T11:24:25 + n + + <source>7ea582d4-9ddf-422e-b28f-29760a4c0147</source> + <uuid>86cb844f-296b-40cb-b972-5b1ae8028f7c</uuid> + <isHarvested>n</isHarvested> + <popularity>477</popularity> + <rating>0</rating> + <displayOrder /> + <view>true</view> + <notify>false</notify> + <download>true</download> + <dynamic>false</dynamic> + <featured>false</featured> + <isPublishedToAll>true</isPublishedToAll> + <groupOwner>6</groupOwner> + <groupLogoUuid>11ef92b3-b547-4a35-af4e-7df6852c30b2</groupLogoUuid> + <groupWebsite>http://www.swisstopo.admin.ch</groupWebsite> + <ownername>ltcmi</ownername> + <valid_details> + <type>schematron-rules-geonetwork</type> + <status>1</status> + <ratio>0/1</ratio> + </valid_details> + <valid_details> + <type>schematron-rules-iso-che</type> + <status>1</status> + <ratio>0/45</ratio> + </valid_details> + <valid_details> + <type>xsd</type> + <status>1</status> + <ratio /> + </valid_details> + <valid_details> + <type>schematron-rules-inspire</type> + <status>0</status> + <ratio>3/16</ratio> + </valid_details> + <valid_details> + <type>schematron-rules-iso</type> + <status>1</status> + <ratio>0/63</ratio> + </valid_details> + <valid>0</valid> + <baseUrl>http://www.geocat.ch:80/geonetwork</baseUrl> + <locService>/srv/en</locService> + </ns6:info> + </che:CHE_MD_Metadata> + diff --git a/ckanext/swisstopo/tests/test.xml b/ckanext/swisstopo/tests/test.xml new file mode 100644 index 0000000..1bbf496 --- /dev/null +++ b/ckanext/swisstopo/tests/test.xml @@ -0,0 +1,12 @@ +<test> + <books> + <book language="de"> + <author>Jostein Gaarder</author> + <title>Sofies Welt + + + William Goldman + The Princess Bride + + + diff --git a/pip-requirements.txt b/pip-requirements.txt new file mode 100644 index 0000000..4784c03 --- /dev/null +++ b/pip-requirements.txt @@ -0,0 +1,7 @@ +# This file lists the dependencies of this extension. +# Install with a command like: pip install -r pip-requirements.txt +-e git+https://github.com/liip-forks/ckanclient.git#egg=ckanclient +-e git+https://github.com/okfn/ckanext-importlib.git#egg=ckanext-importlib +OWSLib==0.7.1 +lxml==2.2.4 +boto==2.8.0 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3c6b033 --- /dev/null +++ b/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup, find_packages +import sys, os + +version = '0.0' + +setup( + name='ckanext-swisstopo', + version=version, + description="swisstopo CKAN extension", + long_description="""\ + """, + classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers + keywords='', + author='Liip AG', + author_email='contact@liip.ch', + url='http://www.liip.ch', + license='', + packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), + namespace_packages=['ckanext', 'ckanext.swisstopo'], + include_package_data=True, + zip_safe=False, + install_requires=[ + # -*- Extra requirements: -*- + ], + entry_points=\ + """ + [ckan.plugins] + #swisstopo_plugin=ckanext.swisstopo:PluginClass + [paste.paster_command] + swisstopo=ckanext.swisstopo.commands.swisstopo:SwisstopoCommand + """, +)