I recently had someone give me a potential issue that they were having when using ServiceNow’s SOAP Message library. They were consuming a WSDL where there were N number of the same element. The purpose of these elements in the SOAP body was to allow ServiceNow to send multiple attachments in one SOAP Request. The customer needed a way to insert any number of additional XML elements into the SOAP Message without having the XML escaped or treated as encapsulated CDATA.

I did some digging in the SOAPMessage library and found that in recent releases, ServiceNow has reworked their methods to easily allow just this sort of scenario.

Let’s work through an example on how this is done.

First, let’s take the example “StockQuote” SOAP Web Service in the ServiceNow SOAP Message application. If we look at the SOAP template for “StockQuote.GetQuoteCustom” function, we would see that there is a provision for a variable “${symbol}” that can be inserted into the request.

1
2
3
4
5
6
7
<SOAP-ENV:Envelope>
  <SOAP-ENV:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol xsi:type="xsd:string">${symbol}</symbol>
    </GetQuote>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In real life, the GetQuote SOAP function can handle receiving multiple stock symbols by having the various stock symbols in a comma separated string inside of the ${symbol} variable (eg. “IBM,MSFT,GOOG,AAPL”).

So, our ServiceNow javascript code to call multiple symbols would look traditionally like this:

1
2
3
var s = new SOAPMessage('StockQuote', 'StockQuoteSoap.GetQuote');
s.setParameter('symbol', 'IBM,MSFT,GOOG,AAPL');
var response = s.post();

For this example, however, let’s pretend that if we wanted to query multiple symbols, we would need to have a <symbol> element for each one such as in this XML example:

1
2
3
4
5
6
7
8
9
<SOAP-ENV:Envelope>
  <SOAP-ENV:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>IBM</symbol>
      <symbol>GOOG</symbol>
      <symbol>AAPL</symbol>
    </GetQuote>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In order to get the multiple XML elements into the SOAP message, we would set a variable inside of the GetQuote element, like this:

1
2
3
4
5
6
7
<SOAP-ENV:Envelope>
  <SOAP-ENV:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      ${symbols}
    </GetQuote>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

We would then adjust our script to make use of a newer SOAPMessage function called setXMLParameter(). In fact, according to the code, we should move away from using setParameter() and use either setXMLParameter() or setStringParameter(). The difference between these two functions is that the XML parameters are not escaped whereas String Parameters escape their contents.

So, our code would look something like the following:

1
2
3
4
5
6
7
8
9
//Build the symbol XML
var sXML = "<symbol>IBM</symbol>\n";
sXML += "<symbol>MSFT</symbol>\n";
sXML += "<symbol>GOOG</symbol>\n";
sXML += "<symbol>AAPL</symbol>\n";

var s = new SOAPMessage('StockQuote', 'StockQuoteSoap.GetQuote');
s.setXMLParameter('symbols', sXML);
var response = s.post();

Of course there are other ways of doing this by diving into the SOAP Message Envelope object and traversing your XML tree, but this offers a quick and easy way of inserting a varying number of elements into your SOAP Message.