Skip to main content Stream TDX Bengaluru on Salesforce+. Start learning the critical skills you need to build and deploy trusted autonomous agents with Agentforce. Register for free.
I am getting a unique SOAP response from a SOAP query request I am doing from Salesforce to an external system (AS400). 

This response is a product of a query I send to the external system asking what has changed and to provide certain fields that have changed. If you notice the first response is a map of the fields that will be in the response. "<a1>POLICY.NUMBER</a1> <a2>CLIENT.CODE</a2>"..ect..

I have tried to use XMLStreamReader and the DOM class, but I'm having trouble actually getting to the Item and corresponding A1,A2,A3 elements. Any ideas on how best to handle this response? 

Also, there will be cases where there is more than one record that is returned so I will have to find every "File" that is returned (other than the index File) and make sure to assign all the values associated with that given File. Then continue looping through onto the next File and assign the other fields / values to that record. 

Example of XML Response: 

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Body>

<PassThroughReqResponse xmlns="http://amsservices.com/">

<PassThroughReqResult><?xml version="1.0"?>

<PickResponse>

<Files>

<File sagfile="WORK.7864470">

<Item sagitem="WEBSERVICE.TAGS*WORK.7864470">

<a1>POLICY.NUMBER</a1>

<a2>CLIENT.CODE</a2>

<a3>EFF.DATE</a3>

<a4>EXP.DATE</a4>

<a5>COV</a5>

<a6>INS</a6>

<a7>TERM</a7>

<a8>POLICY.STATUS</a8>

<a9>BILLING.METHOD</a9>

<a10>31</a10>

<a11>32</a11>

<a12>33</a12>

<a13>POLICY.STATUS</a13>

<a14>NEW.REN</a14>

<a15>CHG.TIME</a15>

</Item>

</File>

<File sagfile="WORK.7864470">

<Item sagitem="579615">

<a1>TESTINGNEW</a1>

<a2>ZIMJO1</a2>

<a3>08/08/16</a3>

<a4>08/08/17</a4>

<a5>ARA</a5>

<a6>CER</a6>

<a7>A</a7>

<a9>Agency Bill</a9>

<a14>NEW</a14>

<a15>12:06:46</a15>

</Item>

</File>

</Files>

</PickResponse></PassThroughReqResult>

</PassThroughReqResponse>

</soap:Body>

</soap:Envelope>

Here is a code snippet that I have hacked to work, but it is not efficient and often times hangs due to CPU usage. This continues on for each A⌗ tag. 

 

//Capture SagittaID

List<String> sagittaID = new List<String>();

//List values to be returned

List<String> sagittaResponseTag = new List<String>();

sagittaResponseTag.add('Item');

sagittaResponseTag.add('a1'); //Client Code

sagittaResponseTag.add('a2'); //Policy Number

sagittaResponseTag.add('a3'); //Effective Date

sagittaResponseTag.add('a4'); //Expiration Date

sagittaResponseTag.add('a5'); //Cov

sagittaResponseTag.add('a6'); //Insuror

sagittaResponseTag.add('a7'); //Term

sagittaResponseTag.add('a8'); //Policy Status

sagittaResponseTag.add('a9'); //Billing Method

sagittaResponseTag.add('a10'); //Written Prem

sagittaResponseTag.add('a11'); //Written Agency Prem

sagittaResponseTag.add('a12'); //Writer Producer Prem

sagittaResponseTag.add('a13'); // Policy Status

sagittaResponseTag.add('a14'); // New or Renewal

for (Integer i = 0; i < sagittaResponseTag.size(); i ++) {

while (reader.hasNext()) { //while there are more XML events

if (reader.getEventType() == XmlTag.START_ELEMENT) { //if this is the opening tag

String localName = reader.getlocalName();

String listTag = string.valueOf(sagittaResponseTag.get(i));

System.debug('Inside Loop :' + i + 'Local Tag Name :' + localName + 'Does this equal :' + listTag);

if (sagittaResponseTag.get(i) == reader.getlocalName()) {

if (sagittaResponseTag.get(i) == 'Item' && reader.getLocalName() == 'Item') {

for (Integer a = 0; a < reader.getAttributeCount(); a ++) {

if (reader.getAttributeLocalName(a).equals('sagitem')) {

theSagittaIdValue = reader.getAttributeValueAt(a);

sagittaID.add(theSagittaIdValue);

System.debug('Found SagittaID: ' + i + ' Value :'+ theSagittaIdValue);

}

}

}

}

} reader.next(); //advance to the next XML event

if ('a1' == reader.getlocalName()) {

System.debug('Found A1');

while(reader.hasNext()) { //while there are more XML events

if (reader.getEventType() == XmlTag.END_ELEMENT) { //if this is the closing tag

break; //exist the loop

} else if (reader.getEventType() == XmlTag.CHARACTERS) { //if this is the content between the tags

theSagittaCodeValue = reader.getText();

// grab the content

if(theSagittaCodeValue != null) {

sagittaClientCode.add(theSagittaCodeValue);

System.debug('Sagitta Client Code: Insert' + ':' + theSagittaCodeValue );

}

}

}

} reader.next(); //advance to the next XML event

 
5 answers
  1. Aug 18, 2016, 8:23 AM
    Give the below a try.  It worked for me in the Force.com IDE Anonymous Apex:

     

    String responseXML = '<?xml version=\"1.0\" encoding=\"utf-8\"?> <soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <soap:Body> <PassThroughReqResponse xmlns=\"http://amsservices.com/\"> <PassThroughReqResult> <PickResponse> <Files> <File sagfile=\"WORK.7864470\"> <Item sagitem=\"WEBSERVICE.TAGS*WORK.7864470\"> <a1>POLICY.NUMBER</a1> <a2>CLIENT.CODE</a2> <a3>EFF.DATE</a3> <a4>EXP.DATE</a4> <a5>COV</a5> <a6>INS</a6> <a7>TERM</a7> <a8>POLICY.STATUS</a8> <a9>BILLING.METHOD</a9> <a10>31</a10> <a11>32</a11> <a12>33</a12> <a13>POLICY.STATUS</a13> <a14>NEW.REN</a14> <a15>CHG.TIME</a15> </Item> </File> <File sagfile=\"WORK.7864470\"> <Item sagitem=\"579615\"> <a1>TESTINGNEW</a1> <a2>ZIMJO1</a2> <a3>08/08/16</a3> <a4>08/08/17</a4> <a5>ARA</a5> <a6>CER</a6> <a7>A</a7> <a9>Agency Bill</a9> <a14>NEW</a14> <a15>12:06:46</a15> </Item> </File> </Files> </PickResponse></PassThroughReqResult> </PassThroughReqResponse> </soap:Body> </soap:Envelope>';

    DOM.Document doc = new DOM.Document();

    String toParse = responseXML;

    doc.load(toParse);

    DOM.XMLNode root = doc.getRootElement();

    String nms = root.getNameSpace();

    System.Debug('namespace: ' + nms);

    DOM.XMLNode body = root.getChildElement('Body', nms);

    System.Debug('body: ' + body);

    List<DOM.XMLNode> bodyChildrenList = body.getChildElements();

    for (DOM.XMLNode passThroughReqResponse : bodyChildrenList) {

    System.Debug('passThroughReqResponse: ' + passThroughReqResponse.getName());

    List<DOM.XMLNode> passThroughReqResultList = passThroughReqResponse.getChildElements();

    for (DOM.XMLNode passThroughReqResult : passThroughReqResultList) {

    System.Debug('passThroughReqResult: ' + passThroughReqResult.getName());

    List<DOM.XMLNode> pickResponseList = passThroughReqResult.getChildElements();

    for (DOM.XMLNode pickResponse : pickResponseList) {

    System.Debug('pickResponse: ' + pickResponse.getName());

    List<DOM.XMLNode> filesList = pickResponse.getChildElements();

    for (DOM.XMLNode files : filesList) {

    System.Debug('files: ' + files.getName());

    List<DOM.XMLNode> fileList = files.getChildElements();

    for (DOM.XMLNode file : fileList) {

    System.Debug('file: ' + file.getName());

    List<DOM.XMLNode> itemList = file.getChildElements();

    for (DOM.XMLNode item : itemList) {

    System.Debug('item: ' + item.getName());

    List<DOM.XMLNode> aList = item.getChildElements();

    for (DOM.XMLNode a : aList) {

    System.Debug('a: ' + a.getName());

    System.Debug('text: ' + a.getText());

    }

    }

    }

    }

    }

    }

    }

    Note that I took out '<?xml version="1.0"?>' in your XML response as it's not a valid XML format.  Apex complained about it.

     
Loading
0/9000