24 мая 2019

Простая трансформация

Рассмотрим, как использовать простую трансформацию для парсинга XML-файла.

Допустим, имеем простой XML-файл.

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Name>SuperCompany</Name>
  <Address>Russia, Moscow</Address>
  <Code>AA-001</Code>
  <Employee Type="FT">
    <Name>James</Name>
    <Number>007</Number>
  </Employee>
  <Employee Type="FT">
    <Name>Steve</Name>
    <Number>010</Number>
  </Employee>
</Company>

Создание необходимых типов в словаре


Создадим структуру ZSTEST_COMPANY, по иерархии полей похожую на иерархию узлов в XML-файле.

Структура ZSTEST_EMPLOYEE

ПолеТипДлинаОписание
TYPECHAR2
EMP_NAMECHAR50
EMP_NUMBERNUMC10

Тип таблицы ZTTEST_EMPLOYEE структурой ZSTEST_EMPLOYEE.

Структура ZSTEST_COMPANY

ПолеТипДлинаОписание
COMP_NAMECHAR50
COMP_ADDRESSCHAR100
EMPLOYEEZTTEST_EMPLOYEE

Создание трансформации


В транзакции XSLT_TOOL (или STRANS) ввести имя трансформации, нажать «Создать». Далее ввести краткое описание и выбрать тип S (простая трансформация). Нажать кнопку «Графическая обработка простой трансформации» (Ctrl+Shift+F11). Нажать правой кнопкой в левой части, выбрать «Insert new root».


Нажать зелёную галку. Перетащить элемент COMPANY в правую часть.


Элемент ROOT в левой части можно удалить. Теперь в правой части иерархию узлов нужно привести в соответствие с иерархией в XML-файле. В нашем случае надо сделать элемент TYPE атрибутом. Для этого нажать на нём правой кнопкой и выбрать «Change to attribute». Обратите внимание, что символом таблицы отмечены элементы, которые могут повторяться в XML-файле. Сохраняем и нажимаем «Назад».

В редакторе подкорректируем имена узлов в соответствии с файлом и удалим лишние тэги. Например, в нашем случае тэги <EMPLOYEE> и </EMPLOYEE> лишние.


Обратите внимание, что элементы между <tt:loop> и </tt:loop> могут повторяться в XML-файле. Должно получиться примерно так.


Узлы, которые могут отсутствовать в XML-файле, нужно заключить в <tt:cond></tt:cond>. А узлы, которые нужно пропустить – в <tt:skip></tt:skip>. В примере ниже узел Address может отсутствовать, а узел Code будет пропущен.


ABAP-программа


Теперь ABAP-код как спарсить XML в структуру:

  DATA:
    lt_xml TYPE solix_tab,
    ls_company TYPE zstest_company,
    lr_excep1 TYPE REF TO cx_st_match_element,
    lr_excep2 TYPE REF TO cx_st_match_attribute,
    lv_msg TYPE string.

  TRY.
      CALL TRANSFORMATION ztest_company
        SOURCE XML lt_xml
        RESULT company = ls_company.
    CATCH cx_st_match_element INTO lr_excep1.
      lv_msg = lr_excep1->get_text( ).
    CATCH cx_st_match_attribute INTO lr_excep2.
      lv_msg = lr_excep2->get_text( ).
  ENDTRY.

И обратное преобразование из структуры в XML-файл:

  CLEAR:
    ls_company, ls_employee.

  ls_company-comp_name = 'Company 1'.
  ls_employee-type = 'AA'.
  ls_employee-emp_name = 'Nick'.
  ls_employee-emp_number = '099'.

  TRY .
      CALL TRANSFORMATION ztest_company
        SOURCE company = ls_company
        RESULT XML lt_xml.
    CATCH cx_root.

  ENDTRY.

PS: код трансформации:

<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates" 
              xmlns:ddic="http://www.sap.com/abapxml/types/dictionary" 
              xmlns:def="http://www.sap.com/abapxml/types/defined">
  <tt:root name="COMPANY" type="ddic:ZSTEST_COMPANY"/>
  <tt:template>
    <Company>
      <Name tt:value-ref="COMPANY.COMP_NAME"/>
      <tt:cond>
        <Address tt:value-ref="COMPANY.COMP_ADDRESS"/>
      </tt:cond>
      <tt:skip count="*" name="Code"></tt:skip>
      <tt:loop ref="COMPANY.EMPLOYEE">
        <Employee>
          <tt:attribute name="Type" value-ref="TYPE"/>
          <Name tt:value-ref="EMP_NAME"/>
          <Number tt:value-ref="EMP_NUMBER"/>
        </Employee>
      </tt:loop>
    </Company>
  </tt:template>
</tt:transform>


Комментариев нет:

Отправить комментарий