Как перебирать / отображать переменные из среды в сборку сообщений в IBM Integration Bus (инструментарий)? - PullRequest
0 голосов
/ 27 мая 2018

У меня есть узел SOAP, который извлекает информацию из URL в древовидной структуре.

Затем у меня есть вычислительный узел для определения каждой переменной среды для каждой переменной пространства имен извлечения SOAP.

И, наконец, у меня есть узел сопоставления, чтобы переместить содержимое в мою структуру сборки сообщений в XML.

Ошибка, которая дает мне вот это (В КОМПЬЮТЕРНОМ УЗЛЕ):

Iимеют такую ​​структуру:

ListDocs

Description
DocType
ListTypes
 Attribute
 Lenght
 Description
 Nature
 Required

ListDocs

Description
DocType
ListTypes
 Attribute
 Lenght
 Description
 Nature
 Required

ListDocs

Description
DocType
ListTypes
 Attribute
 Lenght
 Description
 Nature
 Required

Проблема в том, что, когда я делаюопределение переменных, я делаю это как код ниже, в COMPUTE NODE:

WHILE I < InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos  
DO

  SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:description;

  SET Environment.Variables.XMLMessage.return.process.listDocs.tipoDocumento = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:DocType;

  SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.attribute = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:atribbute;

  SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.lenght = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:lenght;

  SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:description;

  SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.nature = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:nature;

  SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.required = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:required;    

  SET I = I+1;

END WHILE;

НО, в моей конечной структуре XML, он только печатает значения моих первых listDocs, и я хочураспечатайте все мои структуры listDocs.

ПРИМЕЧАНИЕ.Я ДОЛЖЕН УДАЛИТЬ ТО, ЧТОБЫ ПЕЧАТЬ ПЕРВЫЙ listDocs, как я уже сказал выше.

Любая помощь?

Мне НУЖНА ПОМОЩЬ, ЧТОБЫ ПОСМОТРЕТЬ СТРУКТУРЫ, С ТОЛЬКО ИЛИ ЧТО-ТО.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Итак, ключом к пониманию IIB и ESQL является то, что вы смотрите на деревья памяти, построенные из узлов.

Каждый узел имеет указатели / ССЫЛКИ на узлы PARENT, NEXTSIBLING, PREVSIBLING, FIRSTCHILD и LASTCHILD.

Узлы также имеют атрибуты FIELDNAME, FIELDNAMESPACE, FIELDTYPE и FIELDVALUE.

но не в последнюю очередь, что вы строите Деревья вывода, перемещаясь по Деревьям ввода.Дерево среды, которое вы используете, представляет собой специальное долговечное дерево, из которого вы можете как читать, так и записывать.

Итак, в вашем коде InputRoot.SOAP.Body.ns75: processo.ns75:listDocs можно рассматривать как сокращение для инструкций по переходу к узлу ns75: listDocs .Точки "."сообщить интерпретатору ESQL имя дочернего узла текущего узла.Если бы вы говорили кому-то, как перемещаться по узлам, это бы выглядело примерно так:

  1. Начните с InputRoot .InputRoot - это специальный узел, который автоматически доступен для вас в коде модулей ESQL.
  2. Перейдите к первому дочернему узлу InputRoot с именем SOAP
  3. Перейдите к первому дочернему узлу SOAP с именем Body
  4. Перейдите к первому дочернему узлу Body , которыйимеет имя listDocs и находится в пространстве имен ns75 .

При отсутствии нижнего индекса ESQL предполагает, что вам нужен первый узел, соответствующий указанному имени ns75: listDocs и ns75: listDocs [1] оба ссылаются на один и тот же узел.

Это объясняет, что происходило в вашем коде.Вы всегда переходили к одному и тому же узлу listDocs [1] в деревьях InputRoot и Environment .

@ Код Джерема улучшает то, что вы делали, по крайней мере, перемещаясь по узлам listDocs в дереве ввода.

Для каждой итерации цикла нижний индекс [I] увеличивается и, таким образом, выбирается другой listDocs Node.Узлы listDocs являются братьями и сестрами, поэтому код будет обращаться к первому, второму и третьему экземплярам узлов listDocs .

InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[1] <-- Iteration I=1
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[2] <-- Iteration I=2
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[3] <-- Iteration I=3

Чтобы исправить ответ @ Jerem, вынужно будет также использовать подписи в левой части оператора.Выбрав в качестве примера поле description , вам необходимо изменить код следующим образом.

SET Environment.Variables.XMLMessage.return.process.listDocs[I].listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:description;

Использование подписок рассматривается как исполнение № нет.Представьте, что у вас есть 10 000 listDocs , это приведет к тому, что каждая итерация цикла будет идти вниз по дереву по InputRoot , SOAP , Body , ns75: processo Узлы, а затем через узлы listDocs , пока не найден ns75: listDocs [I] Узел.

Thisозначает, что к тому времени, когда мы вернемся к обработке ns75: listDocs [10000] ему придется многократно обходить все остальные listDocs узлы снова и снова. Фактически мы можем вычислитьон прошел бы (4 x 10 000) + ((10 000 x (10 000 + 1)) / 2) = 50 045 000 узлов

Так что это ССЫЛКИ на помощь и также ответ на ваш вопрос .Попробуйте такой цикл.

DECLARE ns75 NAMESPACE 'http://something.or.other.from.your.wsdl';
DECLARE InListDocsRef REFERENCE TO 
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs;
WHILE LASTMOVE(InListDocsRef) DO
    DECLARE EnvListDocsRef REFERENCE TO Environment;
    CREATE LASTCHILD OF Environment.Variables.XMLMessage.return.process AS EnvListDocsRef NAME 'listDocs';

    SET EnvListDocsRef.description           = InListDocsRef.ns75:description;
    SET EnvListDocsRef.tipoDocumento         = InListDocsRef.ns75:DocType;
    SET EnvListDocsRef.listTypes.attribute   = InListDocsRef.ns75:listTypes.ns75:atribbute;
    SET EnvListDocsRef.listTypes.lenght      = InListDocsRef.ns75:listTypes.ns75:lenght;
    SET EnvListDocsRef.listTypes.description = InListDocsRef.ns75:listTypes.ns75:description;
    SET EnvListDocsRef.listTypes.nature      = InListDocsRef.ns75:listTypes.ns75:nature;
    SET EnvListDocsRef.listTypes.required    = InListDocsRef.ns75:listTypes.ns75:required;    

    MOVE InListDocsRef NEXTSIBLING REPEAT NAME;
END WHILE;

Приведенный выше код охватывает только 4 + 10 000 узлов, то есть 10 тысяч узлов против 50 миллионов узлов.

Несколько других полезных вещей, которые нужно знать об установкессылки:

  1. Чтобы указать последний элемент, вы можете использовать индекс [<] </strong>.Таким образом, чтобы указать на последний ListItem в совокупности MyList , вы должны кодировать Environment.MyList.ListItem [<] </strong>
  2. Вы можете использоватьзвездочка * для установки ссылки на элемент в дереве, имя которого вы не знаете, например, Environment.MyAggregate. * указывает на первый дочерний элемент MyAggregate независимо от его имени,
  3. Вы также можете использовать звездочки *, чтобы выбрать элемент независимо от его пространства имен InListDocsRef. *: ListTypes. *: Description
  4. Для анонимных элементов пространства имен используйте *: *, но будьте очень осторожны * и *: * - это не одно и то же: первое означает отсутствие пространства имен для любого элемента, а второе означает любое пространство имен для любого элемента.
  5. Для обработки списков в обратном порядке объедините индекс [<] </strong> с параметром PREVIOUSSIBLING , равным MOVE .

Таким образом, кусок кода для обращения к списку может выглядеть примерно так:

DECLARE MyReverseListItemWalkingRef REFERENCE TO Environment.MyList.ListItem[<];
WHILE LASTMOVE(MyReverseListItemWalkingRef) DO
    CREATE LASTCHILD OF OuputRoot.ReversedList.Item NAME 'Description' VALUE MyReverseListItemWalkingRef.Desc;

    MOVE MyReverseListItemWalkingRef PREVIOUSSIBLING REPEAT NAME;
END WHILE;

Узнайте, как использовать ССЫЛКИ, они чрезвычайно мощные и один из самых простых вариантов, когда речь идет о производительности.

0 голосов
/ 28 мая 2018

Вы должны попытаться использовать следующий синтакс:

DECLARE I INTEGER 1;
DECLARE J INTEGER;
J = CARDINALITY(InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos[])
WHILE I <= J DO
   SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:description;
   ....
END WHILE;

Вы пропустили только функцию CARDINALITY, чтобы получить количество элементов, а также [] для определения таблицы, а затем с помощью этого [I] при доступе к элементам

Примечание: в моем примере выше среда будет переопределена на каждой итерации цикла, поэтому будет напечатана только последняя запись.Вы также можете использовать [I] в выводе, если вы хотите построить таблицу в выводе, или вы можете использовать следующий код для отправки каждого сообщения на выходной терминал (это означает, что у вас есть одно сообщение на входе и 3 сообщениявыходит из выходного терминала)

PROPAGATE TO TERMINAL 'Out';

Так, например, на основе вашего кода, если вы хотите сгенерировать 3 сообщения на основе вашего ввода, содержащего несколько элементов:

DECLARE I INTEGER 1;
DECLARE J INTEGER;
J = CARDINALITY(InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos[])
WHILE I <= J DO
   SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:description;
   SET Environment.Variables.XMLMessage.return.process.listDocs.tipoDocumento = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:DocType;
   SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.attribute = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:atribbute;
   SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.lenght = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:lenght;
   SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:description;
   SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.nature = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:nature;
   SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.required = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:required;
   PROPAGATE TO TERMINAL 'Out';
END WHILE;
RETURN FALSE;

ДляВаша глобальная информация, RETURN TRUE - это инструкция, «отправляющая» сообщение, встроенное в код ESQL, на выходной терминал.Если вы используете инструкцию PROPAGATE (тот же эффект), вы должны RETURN FALSE, чтобы избежать отправки пустого сообщения после зацикливания ваших записей.Другой способ сделать это - распространиться на другой терминал (то есть: 'out1') и сохранить возвращаемое значение true.В этом случае у вас будут все ваши записи, исходящие из терминала out1, и сообщение, выходящее из выходного темринала (из-за возврата true), после того как все сообщения будут распространены (это может быть полезно во многих ситуациях)

...