# Импорт/Экспорт

## Экспорт

Некоторые форматы данных поддерживаются ГИС Аксиома только на импорт и/или экспорт. Не для всех форматом можно создать, открывать и редактировать данные, используя транзакционную модель редактирования, являющуюся основной для ГИС Аксиома. Тем не менее экспорт и создание очень близки по назначению, поэтому они объединены и представлены одним типом `axipy.Destination` - назначение объекта данных.

Так для некоторых типов экспорт `axipy.Destination.export()` является единственной возможностью вывода, в то время как для других - это дополнительная возможность к имеющейся `axipy.Destination.create_open()` в случаях, когда открытие и редактирование не требуется.

Экспортировать можно отдельные записи, таблицы или целые источники данных.

Пример экспорта таблицы в формат CSV

    # Открываем исходную таблицу
    table_src = provider_manager.openfile(input_filepath)
    # Формируем целевую и производим экспорт
    destination = provider_manager.csv.get_destination(output_filepath, Schema())
    destination.export_from_table(table_src, copy_schema=True)

Выполнить экспорт можно так же следующим образом:

Пример экспорта таблицы в формат MIF

    # Открываем исходную таблицу
    table_src = provider_manager.openfile(input_filepath)
    # Формируем целевую и производим экспорт
    destination = provider_manager.mif.get_destination(output_filepath, table_src.schema)
    destination.export(table_src.items())

Если требуется создать таблицу и занести в нее некоторую информацию, но при этом формат данных не поддерживается на изменение, эту проблему можно решить, используя временную таблицу как буфер. Т.е. формируем данные в памяти, а потом производим экспорт этой временной таблицы в нужный нам формат.

Пример формирования файла csv на базе временной таблицы

    # Создаем временную таблицу
    definition = {
        'src': '',
        'schema': attr.schema(
            attr.integer('id'),
            attr.string('name')
        )
    }
    table_src = provider_manager.create(definition)
    # Добавляем в нее записи
    table_src.insert(Feature({'id': '1', 'name': 'Name1'}))
    table_src.insert(Feature({'id': '2', 'name': 'Name2'}))
    # Создаем целевую таблицу и производим экспорт
    destination = provider_manager.csv.get_destination('outfile.csv', Schema())
    destination.export_from_table(table_src, copy_schema=True)

### Пример преобразования в БД

Рассмотрим экспорт таблицы в базу данных на примере.

Для PostgreSQL:

    # откроем исходный файл
    src = provider_manager.openfile('points.tab')
    # Обозначим дополнительные параметры при экспорте. В данном случае это явное пересоздание таблицы
    # и сохранение результатов в лог файле. Данный параметр можно опустить.
    exportParams = ExportParameters()
    exportParams.logFile = 'export.log'
    exportParams.dropTable = True
    # Наименование таблицы в БД
    newTableName = 'points_db'
    # Определяем источник куда будем производить экспорт
    dest = provider_manager.postgre.get_destination(host='db_server_addr',
                                                db_name='test',
                                                dataobject=newTableName,
                                                user='user',
                                                password='pass',
                                                export_params = exportParams,
                                                schema = src.schema)
    # Непосредственно производим экспорт
    dest.export_from_table(src)

Для MSSQL Server:

    dest = provider_manager.mssql.get_destination(host='db_server_addr5',
                                                    db_name='test',
                                                    dataobject=newTableName,
                                                    user='user',
                                                    password='pass',
                                                    export_params = exportParams,
                                                    schema = src.schema)
    dest.export_from_table(src)

### Пример преобразования из DWG и Панорамы

Если требуется экспортировать данные из таких источников, как ГИС Панорама или данных AutoCAD, то это можно сделать двумя путями:

- Вся информация по всем слоям отправляется в один файл

- Производится разбивка по слоям, или же выборочная выборка нужных слоев.

Рассмотрим первый вариант для файла AutoCAD.

    # Откроем исходный файл
    definition = {'src':'input_file.dwg'}
    data_object = provider_manager.open(definition)
    out_folder = '/mnt/hdd/export_folder'
    file_name = os.path.join(out_folder, 'output_file.tab')
    destination = provider_manager.tab.get_destination(file_name, data_object.schema)
    destination.export(data_object.items())

По аналогии для данных ГИС Панорама.

    # Откроем исходный файл
    data_object = provider_manager.openfile('Podolsk.map')
    out_folder = '/mnt/hdd/export_folder'
    file_name = os.path.join(out_folder, 'output_file.tab')
    destination = provider_manager.tab.get_destination(file_name, data_object.schema)
    destination.export(data_object.items())

Рассмотрим второй вариант. Все слои экспортируем как отдельные файлы.

    # Откроем исходный файл
    definition = {'src':'input_file.dwg'}
    data_object = provider_manager.open(definition)
    out_folder = '/mnt/hdd/export_folder'
    # Запросим список слоев и каждый слой экспортируем в отдельный файл
    for layer_name in data_object.layers:
        file_name = os.path.join(out_folder, '.'.join([layer_name, 'tab']))
        destination = provider_manager.tab.get_destination(file_name, data_object.schema)
        destination.export(data_object.items(layer_name))

Список слоев можно взять как у уже открытого объекта посредством метода `axipy.RasteredTable.layers()`, так и у менеджера провайдеров, передав ему определение (как при открытии источника) `axipy.ProviderManager.read_contents()`

Экспортируем один слой из файла формата ГИС Панорама в файл TAB.

    data_object_src = provider_manager.openfile('Podolsk.map')
    out_file_name = 'output_file.tab'
    destination = provider_manager.tab.get_destination(out_file_name, data_object_src.schema)
    destination.export(data_object_src.items('ГИДРОГРАФИЯ'))

### Пример преобразования в DWG и Панораму

Следующим примером произведем конвертацию из формата TAB в формат AutoCAD DWG. При этом последовательно обработаем два файла и поместим данные из них на соответствующие слои.

    out_file_name = 'outfile.dwg'
    # Целевая Система Координат
    cs = CoordSystem.from_prj('0,7')
    # Экспортируем первый файл на слой в AutoCAD 'world'
    table_src = provider_manager.openfile('world.tab')
    destination = provider_manager.dwg.get_destination(out_file_name, table_src.schema, 'world', coordsystem = cs)
    destination.export(table_src.items())
    # Экспортируем второй файл на слой в AutoCAD 'SubjectRF' при этом указывааем open_mode
    table_src = provider_manager.openfile('SubjectRF.TAB')
    destination = provider_manager.dwg.get_destination(out_file_name, table_src.schema,
                                                        'SubjectRF', coordsystem = cs, open_mode = OpenMode.Append)
    destination.export(table_src.items())

Экспортируем таблицу в формате TAB в файл Панорамы SIT. Для этого дополнительно нам необходимо указать классификатор и наименование ключевого поля

    # Файл с классификатором
    rsc = 'Podolsk/Topo100t.rsc'
    # Исходный файл
    table_src = provider_manager.openfile('ГИДРОГРАФИЯ.tab')
    # Наименование целевого файла
    out_filename = 'sit_outfile.sit'
    # Определяем целевой файл
    destination = provider_manager.panorama.get_destination(out_filename, rsc, table_src.schema, 'ObjectKey')
    # Производим экспорт
    destination.export(table_src.items())
    # Экспортируем второй слой
    table_src = provider_manager.openfile('РАСТИТЕЛЬНОСТЬ.tab')
    destination = provider_manager.panorama.get_destination(out_filename, rsc, table_src.schema, 'ObjectKey', open_mode = OpenMode.Append)
    destination.export(table_src.items())

### Преобразование в формат Sqlite и GPKG

Пример экспорта в GPKG последовательно 2-х таблиц в один выходной файл:

    # Определяем имя выходного файл и тип формата (GPKG)
    file_path_out = "out_sqlite_GPKG.gpkg"
    f = SqliteGeometryFormat.GPKG

    # Экспортируем первый файл
    t1 = axipy.provider_manager.openfile('world.tab')
    destination = axipy.provider_manager.sqlite.get_destination(file_path_out, t1.name, t1.schema, geometry_format=f)
    destination.export(t1.items())

    # Экспортируем второй файл
    t2 = axipy.provider_manager.openfile('worldcap.tab')
    destination = axipy.provider_manager.sqlite.get_destination(file_path_out, t2.name, t2.schema, geometry_format=f)
    destination.export(t2.items())

Для экспорта в формат sqlite необходимо изменить строку, задающую выходной формат:

    f = SqliteGeometryFormat.FGF

### Преобразование с использованием библиотеки OGR

Для этого воспользуемся провайдером `axipy.OgrDataProvider`.

Пример экспорта из файла формата MapInfo в Shapefile с созданием пространственного индекса:

    t = axipy.provider_manager.openfile('in/states.tab')
    data = {"lco":{"SPATIAL_INDEX":"YES"}}
    destination = provider_manager.shp.get_destination('out/out_shp.shp', t.schema, create_data=data)
    destination.export(t.items())

Экспорт в источник, который задан строкой соединения. Рассмотрим пример экспорта из файла формата MapInfo в БД PostgreSQL:

    t = axipy.provider_manager.openfile('in/states.tab')
    conn_str="PG:host='localhost' dbname='test' user='test' password='pass' "
    data = {"lco":{"GEOMETRY_NAME":"AXIOMA_GEOMETRY", "FID":"AXIOMA_ID", "OVERWRITE":"YES"}}
    destination = provider_manager.ogr.get_destination(conn_str, 'states', t.schema, create_data=data)
    destination.export(t.items())

Запись двух слоев в sqlite:

    tw = axipy.provider_manager.openfile('in/world.tab')
    twc = axipy.provider_manager.openfile('in/worldcap.tab')
    destination = provider_manager.ogr.get_destination('out_sqlite.sqlite', 'world', tw.schema)
    destination.export(tw.items())
    destination = provider_manager.ogr.get_destination('out_sqlite.sqlite', 'worldcap', twc.schema, open_mode = OpenMode.Append)
    destination.export(twc.items())

В KML:

    destination = provider_manager.ogr.get_destination('out_kml.kml', 'world', t.schema)
    destination.export(t.items())

В GML:

    destination = provider_manager.ogr.get_destination('out_gml.gml', 'world', t.schema)
    destination.export(t.items())

Экспорт из PostgreSQL в GPKG средствами OGR:

    src = provider_manager.postgre.get_source(host='localhost',
                                                    db_name='test',
                                                    dataobject='world',
                                                    user='test',
                                                    password='pass')
    t=axipy.provider_manager.open(src)
    destination = provider_manager.ogr.get_destination('out_sqlite.sqlite', 'worldcap', t.schema, open_mode = OpenMode.Create)
    destination.export(t.items())

## Импорт

Источник данных `axipy.Source` - это зеркальный тип назначения объекта данных `axipy.Destination`. Так же как для назначения, некоторые типы данных поддерживают только импорт, и не могут быть напрямую открыты с помощью `axipy.Source.open`. А другие типы поддерживают и открытие и импорт для случаев, когда открытие и редактирование не требуется.

Пример экспорта источника

    source = provider_manager.tab.get_source(input_tab_file)
    destination.export_from(source)

См.также

Чтобы узнать, какие типы поддерживают импорт и экспорт, обратитесь к описанию конкретных провайдеров данных `axipy.ProviderManager`.

## Изменение структуры таблицы

Если необходимо изменить структуру таблицы, в частности добавить новое поле, удалить существующее или же его расширить. Эту процедуру можно выполнить через экспорт. Рассмотрим на примере.

Откроем исходную таблицу

    # открываем исходный файл
    src = provider_manager.openfile(src_filepath)

Далее, возьмем схему исходной таблицы, сделаем ее копию и произведем все необходимые с ней изменения. Т.е. добавим новое поле в конкретную позицию, удалим ненужное и расширим длину существующего.

    # Целевая схема как копия исходной
    dest_schema = src.schema
    # вставка нового поля
    dest_schema.insert(2, Attribute.string('Новое поле', 30))
    # Удаление поля по имени
    attr_to_del = dest_schema.by_name('Capital')
    dest_schema.remove(attr_to_del)
    # Увеличение длины поля
    idx_edit = dest_schema.index_by_name('Страна')
    dest_schema[idx_edit] = Attribute.string('Страна', 100)

Следующим шагом создаем выходную таблицу на базе полученной схемы и производим непосредственно экспорт.

    # Создаем таблицу
    dest = provider_manager.tab.get_destination(dest_filepath, dest_schema)
    # Экспортируем данные
    dest.export_from_table(src)

Если необходимо создать таблицу в памяти на базе измененной структуры, то эту задачу можно выполнить следующим образом:

    # Создаем таблицу в памяти на базе измененной схемы
    memory_table = provider_manager.create({'schema': dest_schema})
    # Производим вставку данных
    memory_table.insert(src.items())