ФИАС: различия между версиями
Mavka (обсуждение | вклад) м (→MySQL) |
Mavka (обсуждение | вклад) (xml2sql) |
||
Строка 5: | Строка 5: | ||
= Загрузка данных = | = Загрузка данных = | ||
Рассмотрим процесс импорта данных из файлов XML в реляционную базу данных на примере PostgreSQL. Для других БД (MySQL, SQL Server, Oracle и т.п.) процедура потребует незначительной доработки. | |||
=== Структура таблиц === | === Структура таблиц === | ||
XSL Transformation | На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования схема в формат SQL (CREATE TABLE...) применим XSL Transformation (XSLT). В зависимости от БД может потребоваться изменить типы данных колонок. | ||
<div class="toccolours mw-collapsible"> | <div class="toccolours mw-collapsible"> | ||
Строка 22: | Строка 24: | ||
<xsl:variable name="filename" select="lower-case(tokenize(tokenize(base-uri(.), '/')[last()],'\.')[1])" /> | <xsl:variable name="filename" select="lower-case(tokenize(tokenize(base-uri(.), '/')[last()],'\.')[1])" /> | ||
DROP TABLE IF EXISTS <xsl:value-of select="$filename"/>; | |||
CREATE TABLE <xsl:value-of select="$filename"/> ( | CREATE TABLE <xsl:value-of select="$filename"/> ( | ||
<xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" > | <xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" > | ||
<xsl:text> </xsl:text><xsl:value-of select="@name"/><xsl:text> </xsl:text> | |||
<xsl:choose> | <xsl:choose> | ||
<!-- тип данных --> | <!-- тип данных --> | ||
Строка 38: | Строка 41: | ||
<xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" > | <xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" > | ||
<a>COMMENT ON COLUMN <xsl:value-of select="$filename"/>. | <a>COMMENT ON COLUMN <xsl:value-of select="$filename"/>.<xsl:value-of select="@name" /> IS </a> | ||
<xsl:choose> | <xsl:choose> | ||
<!-- Часть комментариев слишком длинная, обрезаем лишние строки --> | |||
<xsl:when test="contains(xs:annotation/xs:documentation,'
')"> | <xsl:when test="contains(xs:annotation/xs:documentation,'
')"> | ||
<a>'<xsl:value-of select="substring-before(xs:annotation/xs:documentation,'
')"/>'</a> | <a>'<xsl:value-of select="substring-before(xs:annotation/xs:documentation,'
')"/>'</a> | ||
Строка 55: | Строка 58: | ||
</div> | </div> | ||
Схема подходит для всех таблиц ФИАС. Для работы требуется парсер, поддерживающий XSLT 2.0. Например, для Windows - [http://sourceforge.net/projects/saxon/ Saxon XSLT Processor] (MPL). Тогда обработка файлов | Схема подходит для всех таблиц ФИАС. Для работы требуется парсер, поддерживающий XSLT 2.0. Например, для Windows - [http://sourceforge.net/projects/saxon/ Saxon XSLT Processor] (MPL). Тогда обработка файлов принимает вид (для версии .NET): | ||
<div class="toccolours mw-collapsible"> | <div class="toccolours mw-collapsible"> | ||
Строка 76: | Строка 79: | ||
=== Импорт данных === | === Импорт данных === | ||
Для работы с большими файлами XML предпочтительнее применять потоковые парсеры. Ниже приводится скрипт ETL Scriptella, использующий java-парсер SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер. | |||
<syntaxhighlight lang="java"> | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE etl SYSTEM "http://scriptella.javaforge.com/dtd/etl.dtd"> | |||
<etl> | |||
<description> | |||
Создание таблицы из файла '../sql' и загрузка данных из файла '../xml' | |||
</description> | |||
<properties> | |||
<include href="db.properties"/> | |||
</properties> | |||
<connection id="in" driver="janino"/> | |||
<connection id="out" driver="${driver}" url="${url}" user="${user}" password="${password}"> | |||
autocommit.size=100 | |||
</connection> | |||
<connection id="err" driver="text" url="errors.log"/> | |||
<script connection-id="out"> | |||
<include href="../sql/###TABLE###.sql" encoding="utf-8"/> | |||
</script> | |||
<query connection-id="in"> | |||
import javax.xml.parsers.SAXParser; | |||
import javax.xml.parsers.SAXParserFactory; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.helpers.DefaultHandler; | |||
SAXParserFactory factory = SAXParserFactory.newInstance(); | |||
SAXParser saxParser = factory.newSAXParser(); | |||
DefaultHandler handler = new DefaultHandler() { | |||
boolean isObject = false; | |||
int recordCnt = 0; | |||
public void startElement(String uri, String localName,String qName, Attributes attr) throws SAXException { | |||
if (qName.equalsIgnoreCase("Object")) { | |||
String names = ""; | |||
String values = ""; | |||
int attrCnt = attr.getLength(); | |||
for (int i=0; i < attrCnt; i++) { | |||
names += attr.getQName(i) + ","; | |||
values += "'" + attr.getValue(i) + "',"; | |||
} | |||
names = names.substring(0, names.length()-1); | |||
values = values.substring(0, values.length()-1); | |||
set("sql_names", names); | |||
set("sql_values", values); | |||
<script connection-id="out"> | |||
INSERT INTO ###TABLE### ($sql_names) VALUES ($sql_values); | |||
</script> | |||
next(); | |||
recordCnt++; | |||
System.out.print("\rprocessed: " + recordCnt); | |||
} | |||
} | |||
}; | |||
System.out.println("\n\n\nConverting..."); | |||
saxParser.parse("../xml/###TABLE###.xml", handler); | |||
</query> | |||
</etl> | |||
</syntaxhighlight> | |||
== MySQL == | == MySQL == |
Версия от 20:02, 6 января 2013
Введение
Наследие КЛАДР...
Загрузка данных
Рассмотрим процесс импорта данных из файлов XML в реляционную базу данных на примере PostgreSQL. Для других БД (MySQL, SQL Server, Oracle и т.п.) процедура потребует незначительной доработки.
Структура таблиц
На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования схема в формат SQL (CREATE TABLE...) применим XSL Transformation (XSLT). В зависимости от БД может потребоваться изменить типы данных колонок.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<xsl:variable name="filename" select="lower-case(tokenize(tokenize(base-uri(.), '/')[last()],'\.')[1])" />
DROP TABLE IF EXISTS <xsl:value-of select="$filename"/>;
CREATE TABLE <xsl:value-of select="$filename"/> (
<xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" >
<xsl:text> </xsl:text><xsl:value-of select="@name"/><xsl:text> </xsl:text>
<xsl:choose>
<!-- тип данных -->
<xsl:when test="xs:simpleType/xs:restriction/@base='xs:integer'">integer</xsl:when>
<xsl:when test="xs:simpleType/xs:restriction/@base='xs:byte'">integer</xsl:when>
<xsl:when test="xs:simpleType/xs:restriction/@base='xs:string'">text</xsl:when>
<xsl:when test="@type='xs:date'">date</xsl:when>
</xsl:choose>
<xsl:if test="@use='required'"> NOT NULL</xsl:if>
<xsl:if test="position()!=last()">,
</xsl:if>
</xsl:for-each>
);
<xsl:for-each select="/xs:schema/xs:element[1]/xs:complexType[1]/xs:sequence[1]/xs:element[1]/xs:complexType[1]/xs:attribute" >
<a>COMMENT ON COLUMN <xsl:value-of select="$filename"/>.<xsl:value-of select="@name" /> IS </a>
<xsl:choose>
<!-- Часть комментариев слишком длинная, обрезаем лишние строки -->
<xsl:when test="contains(xs:annotation/xs:documentation,'
')">
<a>'<xsl:value-of select="substring-before(xs:annotation/xs:documentation,'
')"/>'</a>
</xsl:when>
<xsl:otherwise>'<xsl:value-of select="xs:annotation/xs:documentation"/>'</xsl:otherwise>
</xsl:choose>
<xsl:text>;
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Схема подходит для всех таблиц ФИАС. Для работы требуется парсер, поддерживающий XSLT 2.0. Например, для Windows - Saxon XSLT Processor (MPL). Тогда обработка файлов принимает вид (для версии .NET):
@echo off
SET PATH=%PATH%;d:\Program Files\Saxonica\SaxonHE9.4N\bin
for %%f in (*.xsd) do (
Transform ^
-xsl:xsd2db.xslt ^
-s:%%f ^
-o:sql\%%~nf.sql
)
Далее полученные файлы SQL желательно откорректировать, чтобы явно назначить ключи (primary keys).
//// Ссылка на готовые файлы
Импорт данных
Для работы с большими файлами XML предпочтительнее применять потоковые парсеры. Ниже приводится скрипт ETL Scriptella, использующий java-парсер SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE etl SYSTEM "http://scriptella.javaforge.com/dtd/etl.dtd">
<etl>
<description>
Создание таблицы из файла '../sql' и загрузка данных из файла '../xml'
</description>
<properties>
<include href="db.properties"/>
</properties>
<connection id="in" driver="janino"/>
<connection id="out" driver="${driver}" url="${url}" user="${user}" password="${password}">
autocommit.size=100
</connection>
<connection id="err" driver="text" url="errors.log"/>
<script connection-id="out">
<include href="../sql/###TABLE###.sql" encoding="utf-8"/>
</script>
<query connection-id="in">
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean isObject = false;
int recordCnt = 0;
public void startElement(String uri, String localName,String qName, Attributes attr) throws SAXException {
if (qName.equalsIgnoreCase("Object")) {
String names = "";
String values = "";
int attrCnt = attr.getLength();
for (int i=0; i < attrCnt; i++) {
names += attr.getQName(i) + ",";
values += "'" + attr.getValue(i) + "',";
}
names = names.substring(0, names.length()-1);
values = values.substring(0, values.length()-1);
set("sql_names", names);
set("sql_values", values);
<script connection-id="out">
INSERT INTO ###TABLE### ($sql_names) VALUES ($sql_values);
</script>
next();
recordCnt++;
System.out.print("\rprocessed: " + recordCnt);
}
}
};
System.out.println("\n\n\nConverting...");
saxParser.parse("../xml/###TABLE###.xml", handler);
</query>
</etl>
MySQL
Готовые данные http://basicdata.ru/
Классификаторы России (rus-ref)