# README по лабораторной работе: XML → XSLT → HTML + SQL
## 1. Что это за работа
В этой работе берётся XML-файл со списком специальностей НИЯУ МИФИ, затем:
1. анализируется структура данных;
2. определяется, какие поля есть у сущности `object`;
3. для каждого поля определяется тип данных;
4. для текстовых полей вычисляется максимальная длина значения;
5. определяются ограничения целостности:
- `NOT NULL`, если поле всегда заполнено;
- `CHECK`, если поле принимает от 2 до 5 разных значений;
6. формируется SQL-скрипт для PostgreSQL;
7. пишется XSLT-преобразование;
8. при открытии XML или при запуске Python-скрипта автоматически генерируется HTML-страница с анализом и SQL-кодом.
Идея работы простая:
- **XML** хранит исходные данные;
- **XSLT** описывает, как из XML сделать человекочитаемую HTML-страницу;
- **SQL** — это уже результат проектирования таблицы и генерации команд вставки;
- **Python** нужен как запасной способ генерации HTML, если браузер неудобно применяет XSLT.
---
## 2. Короткая теория
### 2.1. Что такое XML
XML — это язык разметки для хранения структурированных данных.
Пример:
```xml
```
Здесь:
- `object` — одна запись;
- `id`, `name`, `code` — поля этой записи;
- текст внутри тега — само значение;
- атрибут `type="integer"` — дополнительная информация о значении.
В этой работе XML используется как **источник данных**.
---
### 2.2. Что такое XSLT
XSLT — это язык преобразования XML.
Он позволяет сказать:
- какие теги брать из XML;
- как их выводить;
- в каком порядке показывать;
- как на основе XML сгенерировать HTML, текст или другой XML.
В нашей работе XSLT делает сразу две вещи:
1. показывает **анализ данных**;
2. генерирует **SQL-код**.
То есть XSLT здесь — это «шаблон», который читает XML и печатает из него понятный результат.
---
### 2.3. Что такое HTML в этой работе
HTML здесь не пишется вручную как обычная страница сайта.
Он **генерируется автоматически** из XML через XSLT.
Это важный смысл задания: показать именно преобразование, а не ручную вёрстку.
---
### 2.4. Что такое SQL в этой работе
SQL-файл нужен для базы данных PostgreSQL.
Он содержит:
1. удаление старых объектов, если они уже есть;
2. создание последовательности;
3. создание таблицы;
4. отдельные `INSERT`-запросы для каждой записи из XML.
---
### 2.5. Что такое `NOT NULL`
`NOT NULL` означает: значение в этом столбце обязательно должно быть.
Если в XML поле ни разу не пустое, значит для таблицы логично поставить `NOT NULL`.
Пример:
```sql
name VARCHAR(102) NOT NULL
```
Это значит, что у записи не может быть пустого `name`.
---
### 2.6. Что такое `CHECK`
`CHECK` — это ограничение, которое разрешает только некоторые значения.
Пример:
```sql
CHECK (level IN ('Специалитет', 'Магистратура', 'Бакалавриат', 'Аспирантура'))
```
Это значит: в поле `level` можно записать только одно из этих значений.
Такое ограничение удобно, когда уникальных вариантов мало и они заранее известны.
---
### 2.7. Что такое последовательность `SEQUENCE`
Последовательность — это объект БД, который выдаёт новые числа по порядку.
В PostgreSQL значение берётся так:
```sql
nextval('specialities_id_seq')
```
В задании сказано, что `id` при вставке нужно брать **не из XML**, а из последовательности.
То есть XML-значение `id` анализируется, но при вставке в таблицу мы используем новый номер из sequence.
---
### 2.8. Почему HTML не читает `.sql` напрямую
HTML-страница в этой работе строится не из SQL-файла, а из XML через XSLT.
Схема такая:
```text
specialities.xml + specialities.xsl -> HTML
```
Поэтому если изменить только `.sql`, страница сама не поменяется.
Нужно менять XSLT или заново сгенерировать HTML через XML + XSLT.
---
## 3. Какие файлы есть в работе
### Основные файлы
- `specialities.xml` — исходные данные в XML;
- `specialities.xsl` — XSLT-преобразование;
- `specialities.sql` — SQL-скрипт для PostgreSQL;
- `specialities.html` — готовый результат преобразования;
- `transform.py` — Python-скрипт для генерации HTML.
---
## 4. Общая логика работы по шагам
### Шаг 1. Берём XML
В XML есть корневой тег `objects`, а внутри него много тегов `object`.
Каждый `object` — одна специальность.
### Шаг 2. Анализируем поля
У каждого `object` есть поля:
- `id`
- `name`
- `code`
- `level`
- `level-id`
- `generation`
- `generation-id`
- `type`
- `type-id`
### Шаг 3. Для каждого поля определяем свойства
- тип данных;
- число пустых значений;
- для текста — максимальную длину;
- нужен ли `NOT NULL`;
- нужен ли `CHECK`.
### Шаг 4. Генерируем SQL-структуру таблицы
На основе анализа создаются:
- последовательность `specialities_id_seq`;
- таблица `specialities`;
- ограничения `NOT NULL` и `CHECK`.
### Шаг 5. Генерируем SQL-вставки
Для каждого `object` создаётся **отдельный** `INSERT`.
### Шаг 6. Генерируем HTML
XSLT выводит на страницу:
- анализ полей;
- SQL для создания таблицы и sequence;
- SQL `INSERT` для каждого объекта.
### Шаг 7. При необходимости запускаем Python
Python-скрипт берёт XML и XSLT и сохраняет готовый HTML-файл.
---
## 5. Подробно по каждому файлу
# 5.1. Файл `specialities.xml`
## Что делает файл
Это исходный набор данных. Он ничего сам не вычисляет. Он только хранит записи.
## Как устроен файл
У файла повторяющаяся структура. Поэтому подробно важно понять **первые строки и один типовой блок `object`**. Дальше всё повторяется по той же схеме.
## Разбор структуры по строкам
### Строка 1
```xml
```
Что делает:
- объявляет XML-документ;
- указывает версию XML;
- задаёт кодировку UTF-8.
Зачем нужна:
- чтобы парсер понимал, что это XML;
- чтобы русские буквы читались правильно.
### Строка 2
```xml
```
Что делает:
- открывает корневой контейнер;
- атрибут `type="array"` говорит, что внутри набор однотипных объектов.
Зачем нужна:
- у XML должен быть один корневой элемент;
- все записи нужно куда-то вложить.
### Строка 3
```xml
```
Что делает:
- закрывает одну запись.
### Строки 14 и далее
Дальше идёт следующий `object` с точно такой же структурой:
- открывается ``.
То есть весь файл дальше — это просто повторение одной и той же схемы для разных специальностей.
### Последняя строка файла
```xml
```
Что делает:
- закрывает корневой контейнер.
## Простое объяснение
XML-файл — это как большая таблица, только записанная не в строках Excel, а во вложенных тегах.
---
# 5.2. Файл `specialities.xsl`
## Что делает файл
Это главный логический файл работы.
Он:
1. читает XML;
2. выводит анализ полей;
3. собирает SQL-код создания таблицы;
4. выводит отдельные `INSERT` по всем объектам;
5. формирует итоговый HTML.
Ниже — подробный разбор по строкам и блокам.
## Разбор файла `specialities.xsl`
### Строка 1
```xml
```
Это объявление XML для самого XSLT-файла.
### Строка 2
```xml
```
Что делает:
- открывает XSLT-документ;
- объявляет пространство имён `xsl`;
- указывает, что используется XSLT 1.0.
Зачем нужно:
- без этого процессор не поймёт, что перед ним XSLT.
### Строка 3
```xml
```
Что делает:
- говорит, что результат преобразования будет HTML;
- кодировка UTF-8;
- `indent="yes"` просит красиво форматировать результат.
---
## Блок ключей: строки 5–11
```xml
...
```
Что делают ключи:
- помогают находить уникальные значения;
- используются для формирования `CHECK`.
Простыми словами:
- если в XML много раз встречается `Специалитет`, ключ позволяет взять это значение один раз, а не печатать его сто раз.
Используемые ключи:
- `k-level`
- `k-level-id`
- `k-generation`
- `k-generation-id`
- `k-type`
- `k-type-id`
---
## Блок `escape-sql`: строки 13–28
Это шаблон для экранирования одинарных кавычек в SQL.
### Строка 14
```xml
```
Создаёт именованный шаблон.
### Строка 15
```xml
```
Принимает входной текст.
### Строки 16–27
Логика такая:
- если в тексте есть `'`,
- то она заменяется на `''`,
- потому что в SQL именно так экранируют одинарную кавычку.
Зачем это нужно:
- чтобы SQL не ломался на строковых значениях.
---
## Блоки `show-not-null-text` и `sql-not-null`: строки 30–43
### `show-not-null-text`
Выводит на HTML строку:
```html
Нужен: NOT NULL
```
только если число пустых значений равно 0.
### `sql-not-null`
Добавляет в SQL-фрагмент текст:
```sql
NOT NULL
```
тоже только если пустых значений нет.
Это важно, потому что ограничение теперь не написано «по умолчанию», а выводится по фактическому анализу XML.
---
## Главный шаблон `match="/"`: строки 45–118
Это входная точка преобразования.
Когда XSLT начинает работу, он сначала попадает именно сюда.
### Строки 46–58
Создают обычную HTML-обёртку:
- ``
- ``
- ``
- ``
- `