1

I'm trying to create the response for my soap web service in IBM integration Bus. I'm using ESQL compute node to generate the XML using XMLNS. I have to add some repeating element root nodes to my xml, and that is what I'am facing trouble with.

DECLARE tnsp NAMESPACE '...';

SET OutputRoot.XMLNS.Response.(XML.NamespaceDecl)xmlns:acc = tnsp;
SET OutputRoot.XMLNS.Response.tnsp:ReqID = 'ID102';
SET OutputRoot.XMLNS.Response.tnsp:CompanyName = 'Example';

SET OutputRoot.XMLNS.Response.tnsp:Employee.tnsp:id = 'E100';
SET OutputRoot.XMLNS.Response.tnsp:Employee.tnsp:name = 'John';

This gives

<Response xmlns:acc="...">
    <acc:ReqID>ID102</acc:ReqID>
    <acc:CompanyName>Example</acc:CompanyName>
    <acc:Employee>
        <acc:id>E100</acc:id>
        <acc:name>John</acc:name>
    </acc:Employee>
</Response>

I want to add more employee nodes, like

<Response xmlns:acc="...">
    <acc:ReqID>ID102</acc:ReqID>
    <acc:CompanyName>Example</acc:CompanyName>
    <acc:Employee>
        <acc:id>E100</acc:id>
        <acc:name>John</acc:name>
    </acc:Employee>
    <acc:Employee>
        <acc:id>E101</acc:id>
        <acc:name>Alex</acc:name>
    </acc:Employee>
    .
    .
    .
</Response>

How can I achieve this? I have tried repeating the code for adding employee node, but it's replacing the existing and output the last updated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Sivaprasad
  • 151
  • 10

2 Answers2

0

It can be achieved by making the Employeenode to a array

SET OutputRoot.XMLNS.Response.tnsp:Employee[1].tnsp:id = 'E100';
Sivaprasad
  • 151
  • 10
0

Another alternative, and generally preferable performance wise, is to use CREATE and REFERENCE's. I created a simple test flow.

enter image description here

The Transform ComputeNode contains the following code.

BROKER SCHEMA com.nsd

CREATE COMPUTE MODULE Transform
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
    -- Declare the namespaces we want to use
    DECLARE acc NAMESPACE 'http://acc';    
    DECLARE soap NAMESPACE 'http://schemas.xmlsoap.org/soap/envelope/';

    -- Create the SOAP aggregate assigning the SOAP parser by using DOMAIN 'SOAP'
    CREATE LASTCHILD OF OutputRoot DOMAIN 'SOAP';

    -- By using the following statements to create elements in the SOAP.Context subtree
    -- our output will use namespace prefixes of soap and acc rather than NS1 and NS2
    SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:soap = soap;
    SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:acc = acc;

    -- Create the main Response aggregate inside the SOAP.Body
    DECLARE ResponseRefOut REFERENCE TO OutputRoot;
    CREATE LASTCHILD OF OutputRoot.SOAP.Body AS ResponseRefOut NAMESPACE acc NAME 'Response';

    -- Add the non repeating aggregate field
    DECLARE EmployeeListRefIn REFERENCE TO InputRoot.SOAP.Body.employeeList;
    SET ResponseRefOut.acc:ReqID = 'ID' || EmployeeListRefIn.requestId;
    SET ResponseRefOut.acc:CompanyName = EmployeeListRefIn.company;

    -- Loop through the employee's in the input creating Employee aggregates in the output
    DECLARE EmployeeRefOut REFERENCE TO OutputRoot;
    DECLARE EmployeeRefIn REFERENCE TO EmployeeListRefIn.employee;
    WHILE LASTMOVE(EmployeeRefIn) DO
        CREATE LASTCHILD OF ResponseRefOut AS EmployeeRefOut NAMESPACE acc NAME 'Employee';

        SET EmployeeRefOut.acc:id = EmployeeRefIn.id;
        SET EmployeeRefOut.acc:name = EmployeeRefIn.firstName;

        MOVE EmployeeRefIn NEXTSIBLING REPEAT NAME;
    END WHILE;

    RETURN TRUE;
END;
END MODULE;

And the following input data to test it with.

<?xml version="1.0"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header/>
    <soap:Body>
        <employeeList>
            <requestId>102</requestId>
            <company>Universal Happiness</company>
            <employee>
                <id>E100</id>
                <firstName>John</firstName>
            </employee>
            <employee>
                <id>E101</id>
                <firstName>Peter</firstName>
            </employee>
            <employee>
                <id>E102</id>
                <firstName>Paul</firstName>
            </employee>
        </employeeList>
    </soap:Body>
</soap:Envelope>

And this shows what the Trace node configuration looks like.

enter image description here

It produces the following output.
Note the three parsers which have the form [{ParserName} : {ParserInstance}] that have been attached to the element tree. Namely SOAPRoot, MQPROPERTYPARSER, and SOAP.

Trace showing the content of the response message

( ['SOAPRoot' : 0x1b633e9ff60]
  (0x01000000:Name  ):Properties = ( ['MQPROPERTYPARSER' : 0x1b406434d80]
    (0x03000000:NameValue):MessageSet             = NULL
    (0x03000000:NameValue):MessageType            = NULL
    (0x03000000:NameValue):MessageFormat          = NULL
    (0x03000000:NameValue):Encoding               = NULL
    (0x03000000:NameValue):CodedCharSetId         = NULL
    (0x03000000:NameValue):Transactional          = NULL
    (0x03000000:NameValue):Persistence            = NULL
    (0x03000000:NameValue):CreationTime           = NULL
    (0x03000000:NameValue):ExpirationTime         = NULL
    (0x03000000:NameValue):Priority               = NULL
    (0x03000000:NameValue):ReplyIdentifier        = NULL
    (0x03000000:NameValue):ReplyProtocol          = 'SOAP-AXIS2' (CHARACTER)
    (0x03000000:NameValue):Topic                  = NULL
    (0x03000000:NameValue):ContentType            = NULL
    (0x03000000:NameValue):IdentitySourceType     = NULL
    (0x03000000:NameValue):IdentitySourceToken    = NULL
    (0x03000000:NameValue):IdentitySourcePassword = NULL
    (0x03000000:NameValue):IdentitySourceIssuedBy = NULL
    (0x03000000:NameValue):IdentityMappedType     = NULL
    (0x03000000:NameValue):IdentityMappedToken    = NULL
    (0x03000000:NameValue):IdentityMappedPassword = NULL
    (0x03000000:NameValue):IdentityMappedIssuedBy = NULL
  )
  (0x01000000:Folder):SOAP       = ( ['SOAP' : 0x1b62a218430]
    (0x01000000:Folder):Context = (
      (0x01000000:Folder):Namespace = (
        (0x03000102:NamespaceDecl)xmlns:soap = 'http://schemas.xmlsoap.org/soap/envelope/' (CHARACTER)
        (0x03000102:NamespaceDecl)xmlns:acc  = 'http://acc' (CHARACTER)
      )
    )
    (0x01000000:Folder):Body    = (
      (0x01000000:Folder)http://acc:Response = (
        (0x03000000:PCDataField)http://acc:ReqID       = 'ID102' (CHARACTER)
        (0x03000000:PCDataField)http://acc:CompanyName = 'Universal Happiness' (CHARACTER)
        (0x01000000:Folder     )http://acc:Employee    = (
          (0x03000000:PCDataField)http://acc:id   = 'E100' (CHARACTER)
          (0x03000000:PCDataField)http://acc:name = 'John' (CHARACTER)
        )
        (0x01000000:Folder     )http://acc:Employee    = (
          (0x03000000:PCDataField)http://acc:id   = 'E101' (CHARACTER)
          (0x03000000:PCDataField)http://acc:name = 'Peter' (CHARACTER)
        )
        (0x01000000:Folder     )http://acc:Employee    = (
          (0x03000000:PCDataField)http://acc:id   = 'E102' (CHARACTER)
          (0x03000000:PCDataField)http://acc:name = 'Paul' (CHARACTER)
        )
      )
    )
  )
)
TJA
  • 2,969
  • 2
  • 25
  • 32
  • Thanks for your reply sir. I have tried your code but I'm getting an error 'BIP2291E: No constant for parser class name for root element name ''Response''. The integration node could not locate a constant for a parser class name for a root element name'. does this work with XMLNS? – Sivaprasad May 13 '19 at 07:47
  • Sorry I only presented a fragment. The reason you are getting the BIP2291E is that IIB searches the tree looking for the name of a Parser to use. I'm not 100% sure why it attaches the XMLNS parser in your code sample. Anyway I've deliberately forced it to used the XMLNS parser by specifying DOMAIN 'XMLNS'. Hopefully this should now work for you. – TJA May 13 '19 at 11:24
  • BTW you can connect a TRACE node immediately after you compute node, configure it to write to a file and specify ${Root} and it will write out the tree including the names of the Parsers that it will use. – TJA May 13 '19 at 11:30
  • Thanks for replying sir, but it's still not working! The trace node wrote nothing to the file. – Sivaprasad May 13 '19 at 12:14
  • BTW as Trace nodes hold the file open you may need to stop and restart the Application before you see the output from the Trace node. – TJA May 20 '19 at 00:02