Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SOAP response (XML) to JSON

I need to consume a SOAP web service which, naturally, sends its response in XML, since I'm developing a Appcelerator Titanium mobile app I would prefer the response in JSON. After looking online I converted the response using this Javascript code, it mostly worked but returned results such as the following:

{
    "SOAP-ENV:Body" :     {
        "ns1:linkAppResponse" :         {
            "ns1:result" :             {
                #text : true;
            };
            "ns1:uuid" :             {
                #text : "a3dd915e-b4e4-43e0-a0e7-3c270e5e7aae";
            };
        };
    };
}

Of course the colons and hashes in the caused problems so I adjusted the code to do a substring on the name and drop off anything before the ':', then a stringified the resulting JSON, removed all the hashes and parsed the JSON again. This is a bit messy for my liking but I end up with something usable.

Here is the xmlToJson code I'm using:

// Changes XML to JSON
function xmlToJson(xml) {

    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) {// element
        // do attributes
        if (xml.attributes.length > 0) {
            obj["@attributes"] = {};
            for (var j = 0; j < xml.attributes.length; j++) {
                var attribute = xml.attributes.item(j);
                obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
            }
        }
    } else if (xml.nodeType == 3) {// text
        obj = xml.nodeValue;
    }

    // do children
    if (xml.hasChildNodes()) {
        for (var i = 0; i < xml.childNodes.length; i++) {
            var item = xml.childNodes.item(i);
            var nodeName = item.nodeName.substring(item.nodeName.indexOf(":") + 1);
            if ( typeof (obj[nodeName]) == "undefined") {
                obj[nodeName] = xmlToJson(item);
            } else {
                if ( typeof (obj[nodeName].push) == "undefined") {
                    var old = obj[nodeName];
                    obj[nodeName] = [];
                    obj[nodeName].push(old);
                }
                obj[nodeName].push(xmlToJson(item));
            }
        }
    }
    return obj;
};

module.exports = xmlToJson; 

Which results in the following JSON:

{
    Body :     {
        linkAppResponse :         {
            result :             {
                text : true;
            };
            uuid :             {
                text : "9022d249-ea8a-47a3-883c-0f4cfc9d6494";
            };
        };
    };
}

While this returns a JSON object I can use, I would prefer to have the resulting JSON in the following form:

{
    result : true;
    uuid : "9022d249-ea8a-47a3-883c-0f4cfc9d6494";
};

Mostly so it's less verbose and I can simply call json.result in order check if the query was successful instead of json.Body.linkAppResponse.result.text

Any help is greatly appreciated.

like image 241
JonoCoetzee Avatar asked Jun 26 '13 07:06

JonoCoetzee


People also ask

Is it possible to change SOAP web service response from XML to JSON?

I've requirement to change my SOAP Web service (WSDL) response from XML to JSON, my request remains same as XML. If it is possible please let me know how to do it. This is not possible by default, SOAP Web Services are working with XML only.

How to convert XML data to JSON format?

It helps to convert your XML data to JSON format. This tool allows loading the XML URL, which loads XML and converts to String. Click on the URL button, Enter URL and Submit. Users can also convert XML File to JSON by uploading the file. Once you are done with XML to JSON converting. You can download as a file or Create a link and Share.

What is JSON Schema?

JSON Schema specifies a JSON-based format to define the structure of JSON data for validation, documentation, and interaction control. It provides a contract for the JSON data required by a given application, and how that data can be modified. JSON Schema is based on the concepts from XML Schema (XSD), but is JSON-based.

What is a namespace in XML SOAP?

XML namespaces are another key component of XML SOAP. A namespace is a collection of names that one could use as element or attribute names, and the namespace uniquely describes these elements or attributes to avoid conflicts. Using an online SOAP Web Service as described here, it sums two numbers and returns the result.


1 Answers

Came up with a working solution, not any less dirty but it works and returns data in the format I want.

function soapResponseToJson(xml) {
    var json = xmlToJson(xml).Body;

    console.debug(json);

    var response = {};
    for (var outterKey in json) {
        if (json.hasOwnProperty(outterKey)) {
            temp = json[outterKey];
            for (var innerKey in temp) {
                if (temp.hasOwnProperty(innerKey)) {
                    response[innerKey] = temp[innerKey].text;
                }
            }
        }
    }

    console.debug(response);
    return response;
}

// Changes XML to JSON
function xmlToJson(xml) {

    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) {// element
        // do attributes
        if (xml.attributes.length > 0) {
            obj["@attributes"] = {};
            for (var j = 0; j < xml.attributes.length; j++) {
                var attribute = xml.attributes.item(j);
                obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
            }
        }
    } else if (xml.nodeType == 3) {// text
        obj = xml.nodeValue;
    }

    // do children
    if (xml.hasChildNodes()) {
        for (var i = 0; i < xml.childNodes.length; i++) {
            var item = xml.childNodes.item(i);
            var nodeName = item.nodeName.substring(item.nodeName.indexOf(":") + 1).replace('#', '');
            if ( typeof (obj[nodeName]) == "undefined") {
                obj[nodeName] = xmlToJson(item);
            } else {
                if ( typeof (obj[nodeName].push) == "undefined") {
                    var old = obj[nodeName];
                    obj[nodeName] = [];
                    obj[nodeName].push(old);
                }
                obj[nodeName].push(xmlToJson(item));
            }
        }
    }
    return obj;
};

module.exports = soapResponseToJson;

console.debug(json):

{
    linkAppResponse :     {
        result :         {
            text : true;
        };
        uuid :         {
            text : "e4f78c5f-1bc2-4b50-a749-19d733b9be3f";
        };
    };
}

console.debug(response):

{
    result : true;
    uuid : "e4f78c5f-1bc2-4b50-a749-19d733b9be3f";
}

I'm going to leave this question open for a while in case someone comes up with a better solution.

like image 189
JonoCoetzee Avatar answered Sep 22 '22 14:09

JonoCoetzee