Как конвертировать SQL Server SELECT в XML в Mule 4? - PullRequest
1 голос
/ 09 февраля 2020

Как преобразовать следующий SQL вывод в XML, используя Dataweave в Mule 4?

SELECT s.RefId
          ,s.LocalId
          ,s.StateProvinceId
          ,s.SchoolName
          ,e.Email
          ,e.EmailType
      FROM SchoolInfo s
      LEFT OUTER JOIN SchoolEmail e
      ON    e.SchoolRefId = s.RefId
      WHERE s.RefId = :ref_id

Вывод в SQL:

RefId                               LocalId StateProvinceId SchoolName      Email               Type
7FDF722B-6BBA-4BF0-8205-A5380B269EF1    1   SA              Steve's School  steven@gmail.com    prm
7FDF722B-6BBA-4BF0-8205-A5380B269EF1    1   SA              Steve's School  test@gmail.com      sec

XML вывод должен выглядеть следующим образом:

<ns0:SchoolInfo xmlns:ns0="http://www.sifassociation.org/datamodel/au/3.4" RefId="7FDF722B-6BBA-4BF0-8205-A5380B269EF1">
  <ns0:LocalId>1</ns0:LocalId>
  <ns0:StateProvinceId>SA</ns0:StateProvinceId>
  <ns0:SchoolName>Steve's School</ns0:SchoolName>
  <ns0:SchoolEmailList>
    <ns0:Email Type="prm">steven@gmail.com</ns0:Email>
    <ns0:Email Type="sec">test@gmail.com</ns0:Email>
  </ns0:SchoolEmailList>
</ns0:SchoolInfo>

Спасибо, Стив

Ответы [ 2 ]

4 голосов
/ 09 февраля 2020

Вот выражение DW, которое сгенерирует одно и то же XML:

%dw 2.0
output application/xml
ns ns0 http://www.sifassociation.org/datamodel/au/3.4
var rId = payload[0].RefId
var lId = payload[0].LocalId
var sId = payload[0].StateProvinceId
---
ns0#SchoolInfo @(RefId: rId): {
    ns0#LocalId: lId,
    ns0#StateProvinceId: sId,
    ns0#SchoolEmailList: payload reduce (e,acc={}) -> acc ++ {
        ns0#Email @(Type: e.Type): e.Email
    }   
} 

Я предполагаю, что RefId, LocalId и StateProvinceId всегда будут одинаковыми для запроса.

Объяснение reduce: reduce объясняется здесь в деталях вместе с его теоретическими основами. Вот также 1014 * страница документации MuleSoft . Эта последняя страница довольно неплохо объясняет reduce

Теперь, по моим собственным словам, reduce принимает в качестве входных данных (1) массив и (2) лямбда-функцию.

Массив содержит элементы, которые reduce будет перебирать аналогично функции map. Сходство между функциями map и reduce заканчивается здесь:).

Функция лямбда ожидает два аргумента: (1) текущий элемент, который вы перебираете из массива, и (2) аккумулятор. Аккумулятор можно инициализировать в значение (я установил его для объекта {} в вашем случае использования, потому что XML не любит массивы). Результат лямбда-функции для этой FIRST-итерации устанавливается в качестве аккумулятора для следующей итерации и т. Д.

Результатом reduce является аккумулятор после выполнения итерации по массиву.

Таким образом, если бы я должен был отследить этот параметр c reduce, он будет выглядеть примерно так, и я упросту обозначение этих значений:

/*
 * 1st iteration: (e=steven@gmail.com, acc={}) -> acc + {Email: steven@gmail.com}
 * 2nd iteration: (e=test@gmail.com, acc={Email: steven@gmail.com} -> acc + {Email: test@gmail.com}
 * result: acc = {Email: steven@gmail.com, Email: test@gmail.com}
 */
1 голос
/ 09 февраля 2020

Просто продолжение моего комментария выше. Все решение через T- SQL.

SQL

-- DDL and sample data population, start
DECLARE @SchoolInfo TABLE 
(
    RefId VARCHAR(40) PRIMARY KEY,
    LocalId INT,
    StateProvinceId CHAR(2),
    SchoolName VARCHAR(30)
);
DECLARE @SchoolEmail TABLE 
(
    ID INT PRIMARY KEY, 
    RefId VARCHAR(40), 
    Email VARCHAR(30), 
    EmailType CHAR(3)
);
INSERT @SchoolInfo (RefId, LocalId, StateProvinceId, SchoolName) VALUES
('7FDF722B-6BBA-4BF0-8205-A5380B269EF1', 1, 'CA', 'Steve''s School');
INSERT INTO @SchoolEmail (ID, RefId, Email, EmailType) VALUES
(1, '7FDF722B-6BBA-4BF0-8205-A5380B269EF1', 'steven@gmail.com', 'prm')
,(2, '7FDF722B-6BBA-4BF0-8205-A5380B269EF1', 'test@gmail.com ', 'sec');
-- DDL and sample data population, end

DECLARE @ref_id VARCHAR(40) = '7FDF722B-6BBA-4BF0-8205-A5380B269EF1';

;WITH xmlnamespaces ('http://www.sifassociation.org/datamodel/au/3.4' AS ns0)
SELECT s.RefId AS [@RefId]
    , s.LocalId AS [ns0:LocalId]
    , s.StateProvinceId AS [ns0:StateProvinceId]
    , s.SchoolName AS [ns0:SchoolName]
, (
    SELECT e.EmailType AS [ns0:Email/@Type]
        , e.Email AS [ns0:Email]
    FROM @SchoolEmail AS e
    WHERE e.RefId = s.RefId
    FOR XML PATH(''), TYPE, ROOT('ns0:SchoolEmailList')
)
FROM @SchoolInfo AS s
WHERE s.RefId = @ref_id
FOR XML PATH('ns0:SchoolInfo'), TYPE;

Выход

<ns0:SchoolInfo xmlns:ns0="http://www.sifassociation.org/datamodel/au/3.4" RefId="7FDF722B-6BBA-4BF0-8205-A5380B269EF1">
  <ns0:LocalId>1</ns0:LocalId>
  <ns0:StateProvinceId>CA</ns0:StateProvinceId>
  <ns0:SchoolName>Steve's School</ns0:SchoolName>
  <ns0:SchoolEmailList xmlns:ns0="http://www.sifassociation.org/datamodel/au/3.4">
    <ns0:Email Type="prm">steven@gmail.com</ns0:Email>
    <ns0:Email Type="sec">test@gmail.com </ns0:Email>
  </ns0:SchoolEmailList>
</ns0:SchoolInfo>
...