There are several ways to handle XML data that is returned from services. The most common is to know the shape of the returned data and then search for the desired data or navigate through the various nodes of the XML document.

While walking the children nodes or doing repeated finds into XML, the data returned from a service can handle many situations. One customer asked how to get the XML from a service into a JSON object. Well, I’d like to show you a few different scenarios that can be problematic when doing this.  I hope this will help anyone facing such a scenario.

To convert the XML to JSON I decided to utilize the jQuery XML to JSON Plugin (thanks to Fyneworks.com for the good work). For this demonstration I wanted an XML service that would return differently shaped XML for the various parameters. The Behind the Name API has just such a service. The shape of the XML will have more details associated with a name but here are two calls and the XML returned.

http://www.behindthename.com/api/lookup.php?name=mary&key=xxxxxxxxx

<response>
    <script/>
    <name_detail>
        <name>Mary</name>
        <gender>f</gender>
        <usages>
            <usage>
                <usage_code>eng</usage_code>
                <usage_full>English</usage_full>
                <usage_gender>f</usage_gender>
            </usage>
            <usage>
                <usage_code>eng-bibl</usage_code>
                <usage_full>Biblical</usage_full>
                <usage_gender>f</usage_gender>
            </usage>
        </usages>
    </name_detail>
</response>

http://www.behindthename.com/api/lookup.php?name=terry&key=xxxxxxx

<response>
    <script/>
    <name_detail>
        <name>Terry</name>
        <number>1</number>
        <gender>mf</gender>
        <usages>
            <usage>
                <usage_code>eng</usage_code>
                <usage_full>English</usage_full>
                <usage_gender>mf</usage_gender>
            </usage>
        </usages>
    </name_detail>
    <name_detail>
        <name>Terry</name>
        <number>2</number>
        <gender>mf</gender>
        <usages>
            <usage>
                <usage_code>eng</usage_code>
                <usage_full>English</usage_full>
                <usage_gender>m</usage_gender>
            </usage>
            <usage>
                <usage_code>eng</usage_code>
                <usage_full>English</usage_full>
                <usage_gender>f</usage_gender>
            </usage>
        </usages>
    </name_detail>
</response>

The call for “Terry” returned two different name_detail nodes and in the first name_detail node only has one usage node. This is going to result in different shaped JSON objects that we will have to account for in out code.

For Mary, the resulting JSON looks like:

{
    "name_detail": {
        "name": "Mary",
        "gender": "f",
        "usages": {
            "usage": [
                {
                    "usage_code": "eng",
                    "usage_full": "English",
                    "usage_gender": "f"
                },
                {
                    "usage_code": "eng-bibl",
                    "usage_full": "Biblical",
                    "usage_gender": "f"
                }
            ]
        }
    }
}

For Terry, it looks like:

{
    "name_detail": [
        {
            "name": "Terry",
            "number": "1",
            "gender": "mf",
            "usages": {
                "usage": {
                    "usage_code": "eng",
                    "usage_full": "English",
                    "usage_gender": "mf"
                }
            }
        },
        {
            "name": "Terry",
            "number": "2",
            "gender": "mf",
            "usages": {
                "usage": [
                    {
                        "usage_code": "eng",
                        "usage_full": "English",
                        "usage_gender": "m"
                    },
                    {
                        "usage_code": "eng",
                        "usage_full": "English",
                        "usage_gender": "f"
                    }
                ]
            }
        }
    ]
}

So, the The JSON object for Terry will have an array for name_detail while Mary will not. Let's take a look at the code we need to deal with this situation.

if (nameJson.name_detail.length >= 1) {
    $.each(nameJson.name_detail, function() {
        renderNameDetail(this, lookupResultsList);
    });
}
else {
    renderNameDetail(nameJson.name_detail, lookupResultsList);
}

In this 'if' statement we check to see if the name_detail object does not have a length (so it could read “if (nameJson.name_detail.length ==undefined)” but then the logic would be reversed so the code will render with either just the one detail or each detail will be iterated over.

There are also some tweaks needed on the rendered code as well - names with multiple details and also a number field that returned. To handle this, the name detail object can be tested to see if it has that field. We can then render the interface as appropriate.

// Show the number of the name detail if present
if ("number" in nameDetail) {
    $listItem.find(".number").html(nameDetail.number);
    $listItem.find(".numberLabel").css("display", "");
}

The "in" operator will check to see if the object has the "number" property so we can display it when needed.

To see the full demo project check out https://github.com/woodyp/xmlService-Demo


Related Posts

Comments

Comments are disabled in preview mode.