[Из песочницы] XSLT преобразование внутренней таблицы в ABAP, имеющей поле типа «generic reference»
Пролог О чем заметка? Как из внутренней таблицы, строка которой содержит ссылку на неизвестный (обобщенный) тип (REF TO DATA), которая, по факту, хранит ссылку на такую же таблицу, получить XML заданного формата. При этом, число уровней вложенности изначально неизвестно.Зачем это нужно? Мне это понадобилось при выгрузке данных в различные форматы XML-файлов MS Office без использования OLE.Для кого эта заметка? Для программистов на ABAP.Необходимый уровень знания: знать, что такое reference type, generic type, XML; слышать, что существует такая вещь как XSLT.Как же с этим бороться? Задача Есть дерево. Дерево хранится во внутренней таблице. Тип таблицы определен следующим образом: TYPES : BEGIN OF tdeep_struct , name TYPE string , rf_child_list TYPE REF TO data «та самая обобщенная сылка , END OF tdeep_struct
, t_deep_struct TYPE STANDARD TABLE OF tdeep_struct WITH NON-UNIQUE DEFAULT KEY . Т.е. структура строки таблицы в поле rf_child_list содержит ссылку на обобщенный тип (generic type).
Из внутренней таблицы такой структуры, нужно получить XML следующего формата:
При этом расположение узлов исходного дерева в итоговом XML должно соответствовать нисходящему обходу дерева (Т.е. начинаем просмотр записей внутренней таблицы сверху. Выводим содержимое первой записи, если у нее есть зависимые записи в rf_child_list — то начинаем выводить их с первой записи. Если у нее есть зависимые — то следом выводим их и т.д.).
Тестовый пример
Допустим, у нас во внутренней таблице сохранено дерево следующего вида (перечислены значения поля Name):
GrandParent1
Child1
Child2
GrandChild1
GrandParent2
По условиям задачи мы должны получить из этих данных вот такой XML.Итоговый XML для тестового примера
Решение
Начнем с простого: ABAP-код, что же может быть проще? Определим и заполним тестовыми данными внутреннюю таблицу
DATA
: gt_tree TYPE t_deep_struct «таблица дерева
, gtree TYPE tdeep_struct «рабочая область записи первого уровня
, gchild TYPE tdeep_struct «рабочая область записи второго уровня
, ggrandchild TYPE tdeep_struct «рабочая область записи третьего уровня
.
FIELD-SYMBOLS
:
START-OF-SELECTION.
gtree-name = 'GrandParent1'.
CREATE DATA gtree-rf_child_list TYPE t_deep_struct.
ASSIGN gtree-rf_child_list→* TO
gchild-name = 'Child1'.
APPEND gchild TO
gchild-name = 'Child2'.
CREATE DATA gchild-rf_child_list TYPE t_deep_struct.
ASSIGN gchild-rf_child_list→* TO
APPEND gchild TO
APPEND gtree TO gt_tree.
CLEAR gtree.
gtree-name = 'GrandParent2'. APPEND gtree TO gt_tree. Решая задачу я подумал, что надо бы использовать XSLT-преобразование. Так как тэг у этой заметки я поставил «XSLT для начинающих», то надо упомянуть, что же это такое. Если совсем на пальцах, то это такой язык, который позволяет из одного XML получить другой XML. При этом сам XSLT является подмножеством XML. Стоп! А причем тут внутренние таблицы, если он преобразует XML? А это такая особенность реализации XSLT в SAP. Посмотрим подробнее.
За выполнение трансформации в ABAP отвечает оператор CALL TRANSFORMATION. У него много параметром и много вариантов работы.Входные данные требующие преобразования будем передавать, указав SOURCE имя_параметра = имя_внутренней_таблицы.Результат можно получить указав RESULT XML объектXML/внутренняя таблица/строка/объект потока. Для простоты, получать результат будем в строку.
Результат трансформации отобразим на экране стандартными средствами объекта CL_XML_DOCUMENT.Получаем вот такой код:
CALL TRANSFORMATION zedu_test_xslt_deep_transform2 SOURCE table = gt_tree RESULT XML gxml_str.
go_xml_doc→parse_string (gxml_str).
go_xml_doc→display (). Ах да… я же отвлекся! Вопрос-то был: и причем тут трансформация, если вообще-то она для преобразовании одного XML в другой?
Немного rtfm
Начнем с того, что в SAP трансформации используются для сериализации и десериализации данных. Т.е., как из какого-то объекта данных (структуры, внутренней таблицы, объекта) получить представление в виде последовательности битов и наоборот. У нас как раз задача сериализации: на входе вложенная структура (внутренняя таблица ABAP), а на выходе — XML (текстовое представление).XSLT в SAP бывают 2-ух видов: обычный XSLT и simple transformation (ST). SAP показалось мало XSLT и он реализовал свое подмножество XSLT, которое назвал simple transformation. Нам оно не подходит, т.к. не умеет работать с полями generic type в входных параметрах.Остается чистый XSLT.SAP, при выполнении сериализации с применением XSLT, приводит входные параметры трансформации к виду asXML (canonical XML representation). В процессе этого преобразования, по определенным правилам, происходит конверсия типов ABAP, это касается и generic type (Явно получить каноническое представление какой либо переменной можно использовав стандартное для ABAP XSLT преобразование с зарезервированным именем ID).Картинка из хелпа ABAP, объясняющая преобразования данных при трансформацияхДля моего примера каноническое XML представление выглядит следующим образом: