function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
TerminusbotTerminusbot 

Using XMLStreamReader or Dom to Read SOAP Response from AS400

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


 
Best Answer chosen by Terminusbot
UC InnovationUC Innovation
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.

 

All Answers

UC InnovationUC Innovation
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.

 
This was selected as the best answer
TerminusbotTerminusbot
Thank you for this! Looks like this will help me greatly. I do have one quick follow up question. At the Item node there is the following Attribute 'sagitem' and value: <Item sagitem="579615"> How would you get to that attribute value?

I have tried this but getting DOM.XMLNode method errors. 
 
for (DOM.XMLNode file : fileList) {
                    String fileAttrValue;
                    System.Debug('file: ' + file.getName());
                    Integer attrCount = file.getAttributeCount();
                    for (Integer i = 0; i < attrCount; i ++) { 
                        if (file.getAttributeLocalName(i).equals('sagitem')) { 
                            fileAttrValue = file.getAttributeValueAt(i);
                           
                        } 
                    }
                    System.debug('fileAttributeCount' + attrCount); 
                    System.debug('fileAttributeValue' + fileAttrValue);



 
TerminusbotTerminusbot
I got it. I was at the wrong node. It needed to be at the Item not the File. 

Thanks again!
UC InnovationUC Innovation
Here's the updated code for what you are looking for:
 
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());
						System.Debug('sagitem attribute: ' + item.getAttributeValue('sagitem', null));
	
						List<DOM.XMLNode> aList = item.getChildElements();
						
						for (DOM.XMLNode a : aList) {
							System.Debug('a: ' + a.getName());
							System.Debug('text: ' + a.getText());
						}
					}
				}
			}
		}
	}
}

Hope that helps!
TerminusbotTerminusbot
Thanks for your time. Good stuff.