1. Основы XSLT 2.0 и XPath для тестирования
Основы XSLT 2.0 и XPath 2.0: фундамент для тестирования openEHR XML
XSLT (eXtensible Stylesheet Language Transformations) — это язык для преобразования XML-документов в другие форматы: другой XML, HTML, JSON, plain text. Версия 2.0 принципиально отличается от 1.0 поддержкой типов данных, группировки, множественных выходных документов и значительно расширенного набора функций XPath. Именно XSLT 2.0 используется в большинстве современных интеграционных решений на базе openEHR.
Представь XSLT как кулинарный рецепт: входной XML — это сырые ингредиенты, XSLT-таблица стилей — рецепт с инструкциями, а выходной документ — готовое блюдо. Тестирование XSLT — это проверка того, что рецепт всегда даёт правильный результат, даже если ингредиенты неполные или поданы в непривычном порядке.
Как устроен openEHR XML: структура, которую ты будешь трансформировать
Прежде чем писать трансформации и тесты, нужно понять, с каким XML ты работаешь. openEHR использует строго иерархическую модель данных, описанную в Reference Model (RM). XML-схемы для неё опубликованы в компоненте ITS-XML и включают XSD-схемы для RM, AM и BASE компонентов.
Центральный объект — Composition (клиническая запись). Внутри него находятся Section (разделы), которые содержат Entry (клинические записи: Observation, Evaluation, Instruction, Action). Каждый Entry содержит Element — конкретное значение с типом данных.
Ключевая особенность openEHR XML: каждый узел имеет атрибут archetype_node_id с at-кодом — уникальным идентификатором вида at0001, at0002 и т.д. Корневой элемент Composition или Entry дополнительно несёт атрибут archetype_id.
Обрати внимание: элемент items встречается дважды с разными archetype_node_id (at0004 и at0005). Это и есть кардинальность (cardinality) в действии — один и тот же тег-контейнер повторяется для разных клинических концептов. Это одна из главных сложностей при тестировании openEHR-трансформаций.
Анатомия XSLT 2.0 таблицы стилей
Минимальная рабочая XSLT 2.0 таблица стилей выглядит так:
Три ключевых элемента, которые нужно понять сразу:
xsl:template match="..." — шаблон (template): правило, которое срабатывает, когда процессор встречает узел, соответствующий XPath-выражению в matchxsl:apply-templates — команда «обработай дочерние узлы, найди для них подходящие шаблоны»xsl:value-of — вывести текстовое значение узлаПространства имён — первый подводный камень при работе с openEHR XML. Все элементы openEHR находятся в пространстве имён http://schemas.openehr.org/v1. Если ты напишешь match="composition" без префикса ehr:, шаблон никогда не сработает — процессор просто не найдёт узел. Это самая частая ошибка новичков.
XPath 2.0: язык навигации по XML-дереву
XPath 2.0 — это язык запросов к XML-документу. Если XML — это дерево с ветками и листьями, то XPath — это адрес, по которому ты находишь нужную ветку или лист.
Основные оси навигации
| Ось | Что выбирает | Пример |
|-----|-------------|--------|
| child:: (или просто /) | Прямые дочерние узлы | ehr:composition/ehr:content |
| descendant:: (или //) | Все потомки на любой глубине | //ehr:items |
| attribute:: (или @) | Атрибуты узла | @archetype_node_id |
| parent:: | Родительский узел | parent::ehr:data |
| following-sibling:: | Следующие братские узлы | following-sibling::ehr:items |
Предикаты: фильтрация узлов
Предикат — это условие в квадратных скобках, которое фильтрует узлы. Именно предикаты делают XPath мощным инструментом для работы с openEHR:
Функции XPath 2.0, критичные для тестирования
В версии 2.0 появились функции, которых не было в 1.0 и которые особенно важны для тестирования:
Шаблоны XSLT: match vs select
Начинающие часто путают два атрибута — match и select. Разберём разницу на конкретном примере.
match используется в xsl:template и описывает, какой узел активирует этот шаблон. Это как адрес на двери — шаблон «откликается», когда процессор приходит к нужному узлу.
select используется в xsl:apply-templates, xsl:value-of, xsl:for-each и описывает, какие узлы обрабатывать или выводить прямо сейчас.
При обработке нашего примера с артериальным давлением процессор последовательно встретит два узла items и для каждого найдёт свой шаблон по archetype_node_id. Результат:
Режимы шаблонов: обработка одного узла по-разному
Режим (mode) — механизм XSLT, позволяющий применить к одному и тому же узлу разные шаблоны в зависимости от контекста. Это особенно полезно в openEHR, где один и тот же архетип может нужен в разных частях выходного документа.
Переменные и параметры в XSLT 2.0
Переменная (xsl:variable) — именованное значение, которое вычисляется один раз и используется повторно. В отличие от большинства языков программирования, переменные в XSLT неизменяемы после объявления — это важный нюанс.
Типы данных XPath 2.0 и openEHR
XPath 2.0 — строго типизированный язык. Это означает, что сравнение "120" > "80" даст неожиданный результат (лексикографическое сравнение строк), а 120 > 80 — правильный (числовое). В openEHR XML все значения хранятся как текст, поэтому при тестировании числовых условий всегда используй явное приведение типов:
Для дат openEHR использует формат ISO 8601 (2024-03-15T10:30:00). XPath 2.0 умеет работать с датами нативно:
Встроенные шаблоны: невидимая опасность
XSLT имеет встроенные шаблоны (built-in templates), которые срабатывают, если для узла не найдено явного шаблона. По умолчанию встроенный шаблон для элементов и корневого узла — рекурсивно применить шаблоны к дочерним узлам, а для текстовых узлов — вывести их содержимое.
Это значит: если ты забыл написать шаблон для какого-то узла openEHR, его текстовое содержимое всё равно попадёт в выходной документ — просто без тегов. Такой «мусор» в выходном XML очень трудно заметить без тестов.
Защита от этого — явный шаблон-заглушка:
> Встроенные шаблоны XSLT — это «поведение по умолчанию», которое часто приводит к неожиданным результатам в продакшне. Явный шаблон-заглушка — обязательная практика в любой серьёзной трансформации openEHR.
Понимание этих основ — фундамент для всего, что будет дальше: написания тестов на наличие и отсутствие узлов, проверки кардинальности и автоматизации тестирования openEHR-трансформаций. Каждая из этих тем строится именно на XPath-предикатах, шаблонах с match по archetype_node_id и корректной работе с пространствами имён.