0

I am trying to parse the following XML Payload in Apex:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <soap:Header>
        <wsa:Action>UpdateResponse</wsa:Action>
        <wsa:MessageID>urn:uuid:62bffb2d-feb3-44ba-9dea-c43852979252</wsa:MessageID>
        <wsa:RelatesTo>urn:uuid:0baed942-04e1-4b0c-a2de-1085e15ca4d4</wsa:RelatesTo>
        <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
        <wsse:Security>
            <wsu:Timestamp wsu:Id="Timestamp-a1ed0755-8da2-4dce-9eb3-5fb4898faf6b">
                <wsu:Created>2021-08-19T14:42:18Z</wsu:Created>
                <wsu:Expires>2021-08-19T14:47:18Z</wsu:Expires>
            </wsu:Timestamp>
        </wsse:Security>
    </soap:Header>
    <soap:Body>
        <UpdateResponse
            xmlns="http://exacttarget.com/wsdl/partnerAPI">
            <Results>
                <StatusCode>OK</StatusCode>
                <StatusMessage>Updated Subscriber.</StatusMessage>
                <OrdinalID>0</OrdinalID>
                <Object xsi:type="Subscriber">
                    <PartnerKey xsi:nil="true" />
                    <ID>171465903</ID>
                    <ObjectID xsi:nil="true" />
                    <SubscriberKey>myemail@mail.com</SubscriberKey>
                    <Status>Unsubscribed</Status>
                </Object>
            </Results>
            <Results>
                <StatusCode>Error</StatusCode>
                <StatusMessage>InvalidEmailAddress</StatusMessage>
                <OrdinalID>1</OrdinalID>
                <ErrorCode>12000</ErrorCode>
                <Object xsi:type="Subscriber">
                    <PartnerKey xsi:nil="true" />
                    <ObjectID xsi:nil="true" />
                    <SubscriberKey>testmail@mail.com</SubscriberKey>
                    <Status>Active</Status>
                </Object>
            </Results>
            <RequestID>86ba4919-99da-4593-b2e3-622a19b9f361</RequestID>
            <OverallStatus>Has Errors</OverallStatus>
        </UpdateResponse>
    </soap:Body>
</soap:Envelope>

I need to iterate over the Results child items and retrieve the StatusCode, StatusMessage and child SubscriberKey.

I have attemped to this using the following code but I can't get the first attribute:

DOM.Document document = new DOM.Document();
document.load(responseBody);

for (DOM.XmlNode node : document.getRootElement().getChildren())
{
    
    DOM.XmlNode statusCode = node.getChildElement('UpdateResponse', 'http://exacttarget.com/wsdl/partnerAPI');
    String statusMsg = node.getChildElement('Results', null).getAttribute('StatusCode', null);

}
1

Nested data structures like this generally require nested loops to extract data.

for(DOM.XmlNode node : document.getRootElement().getChildren()){ only gets you the direct children of the root element. That is, the <soap:Header> and <soap:Body>

To get at your target data, you need to make some additional calls to getChildren().

Also, an "attribute" in XML is something contained inside of a tag in double quotes. E.g. <myXmlTag IAmAnAttribute="And I'm the attribute's value">. The StatusCode, StatusMessage, and SubscriberKey are all Text nodes of their respective tags

What you're looking for here is something closer to this

String statusCode;

for (DOM.XmlNode node : document.getRootElement().getChildren()){
    if(node.getName() == 'Body'){
        for (DOM.XmlNode node2 : node.getChildren()){
            if(node.getName() == 'UpdateResponse'){
                for (DOM.XmlNode node3 : node2.getChildren()){
                    if(node3.getName() == 'Results'){
                        for (DOM.XmlNode node4 : node3.getChildren()){
                            if(node4.getName() == 'StatusCode'){
                                statusCode = node4.getText();
                            }
                        }
                    }
                }
            }
        }
    }
}
2

Unlike JavaScript's Element.querySelectorAll function, XmlNode.getChildElement() and so on doesn't recursively find child elements. <UpdateResponse> isn't the immediate child of <soap:Envelope>, so you can't get to it without first getting <soap:Body>. If you want be able to recursively find child elements, you need XPath or something similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.