Mobile devices and platforms boast more features and functionality with each new release, and often mere months separate significant announcements from the leading mobile vendors. The headlines are often about UI features or hardware enhancements (such as processor speed, storage capacity, and new communications capabilities such as Near Field Communications). But the crucial fact remains that content is king. Content—or, more generally, data—is exchanged constantly among applications, servers, mobile devices, and users. Without being able to work with it, smartphones such as Apple’s iPhone and Google’s Android simply become overpriced and underperforming cell phones.

Consider the phenomenal success of social-networking platforms such as Facebook, LinkedIn, and Twitter. From a pure feature-and-function perspective, these platforms started as somewhat pedestrian experiences, though their capabilities have grown over time due to the resources poured into those applications. How did those platforms attract such ample resources (in other words, cash)? They have grown because members and site visitors derive value from the content published there. And that content is accessed increasingly by mobile devices.

This article demonstrates the use of XML and JSON data-interchange formats on the Android platform and is an update to an earlier article that interacted with data from Twitter. In the intervening time since the first publication, XML (and its derivatives) have fallen out of favor somewhat and JSON has become more prevalent. Additionally, the market for data interactions has matured from the use of “feeds” to more sophisticated Application Programming Interfaces, or APIs. A “status” feed data used to be available from Twitter in both XML and JSON formats. The XML feed has been dropped and a new JSON API introduced.

As this article is focused on the basics of interacting with XML (still a viable and in-use data format) and JSON, we have replaced the Twitter feed with a “book list” from another site: encouragework.com. The list is provided in both XML and JSON, and as you’ll see, the programming approach to manipulating the data varies significantly between the two formats.

You will want to have the latest version of Android Studio to run the example code that accompanies this article. The Android SDK API revision does not really matter for this application, as the basics of XML and JSON parsing have been available since the early days of Android. To learn more about setting up your environment, visit the Android Developers website.

I’ll begin with a brief look at both data formats, starting with XML. If you’re already familiar with XML and JSON, you can safely skip to Application opportunity: Book List to start working with them on Android.

XML: An old friend

Virtually anyone who has done programming for the enterprise, web, or mobile markets in recent years has encountered XML. It is just about everywhere you look.

An XML document has a recognizable structure: a series of elements that can optionally contain attributes and child elements. Every valid XML document begins with a declaration on the first line: <?xml version="1.0" encoding="utf-8"?>. What comes after the first line is application-dependent. The beauty of XML is that it is self-describing.

XML schemas

Although XML documents are self-describing, they must follow certain rules and guidelines. This is where the XML schema comes in. It is a document that describes the structure of a particular XML file. Such structures are often verbose and complex. (Arguably, XML’s worst contribution to the IT field is the data explosion that took place once the idea of highly descriptive data structures came into fashion, fueled in part by the greatly reduced cost of disk-storage technology in the past decades.)

As these large and complex files became more the norm, the art of working on them manually was often a nonstarter for programmers and analysts. To address this issue, XML editors and validating tools became available to aid in the management of the files and the tasks relating to them, such as documentation and conversion to legacy formats. In addition to general text data, XML can also be used to store binary data through a special set of tags known as CDATA. CDATA tags within an XML document can contain any kind of data, including other mark-up text, provided that text does not contain CDATA itself.

It’s not uncommon for APIs to leverage this capability by using XML as a structure for performing request/response queries. Often the response data contains an XML structure contained within a CDATA tag. For example, an API call might request a customer record with a last name equaling Mott. When the data is found, it is packaged into an XML structure and placed within the response element, as in Listing 1:

Listing 1. Packaging data into an XML structure and placing it within the response element

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request>
<query>
<lastname>Mott</lastname>
<maxhits>100</maxhits>
</query>
</request>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
<returncode>200</returncode>
<query>
<lastname>Mott</lastname>
<hits>1</hits>
</query>
<data>
<![CDATA[
<contact>
<firstname>Troy</firstname>
<lastname>Mott</lastname>
<age>not telling</age>
</contact>
]]>
</data>
</response>

XML in the workplace

XML used to be the default, expected data format, with JSON overtaking it in recent years. Although the same data might be available in other formats too, it is a safe bet to plan on the availability of an XML structure.

Enterprise Resource Planning (ERP) packages use XML heavily for data import and export tasks. Internet news sites often make data available as Really Simple Syndication (RSS) feeds—XML documents with a predefined format that news readers are set up to process. Even word-processing applications such as OpenOffice.org and Microsoft® Office use XML.

Today’s Microsoft Office documents are PKZIP-compatible files containing multiple XML documents. Each XML file shares the common declaration in the first line. As you can see in Listing 2, the attributes can be somewhat hard to follow:

Listing 2. Common declaration in the first line of each XML file

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">
<w:body><w:p w:rsidR="00B6337C" w:rsidRDefault="00663F0E"><w:r>
<w:t xml:space="preserve">This is a sample </w:t></w:r><w:r
w:rsidRPr="006906EA"><w:rPr><w:i/></w:rPr><w:t>Microsoft 
Word document</w:t></w:r><w:r><w:t xml:space="preserve"> used
to </w:t></w:r><w:r w:rsidRPr="006906EA"><w:rPr><w:b/>
<w:u w:val="single"/></w:rPr><w:t>demonstrate</w:t></w:r>
<w:r><w:t xml:space="preserve"> some XML topics.</w:t></w:r>
</w:p><w:p w:rsidR="00B14B2A" w:rsidRDefault="00B14B2A"/><w:p
w:rsidR="00B14B2A"w:rsidRDefault="00B14B2A"><w:r><w:rPr>
<w:noProof/></w:rPr><w:drawing><wp:inline distT="0" distB="0"
distL="0" distR="0"><wp:extent cx="3276600" cy="3838575"/><wp:effectExtent
l="19050" t="0" r="0" b="0"/><wp:docPr id="1" name="Picture 0"
descr="frankableson.jpg"/><wp:cNvGraphicFramePr><a:graphicFrameLocks
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
noChangeAspect="1"/></wp:cNvGraphicFramePr><a:graphic
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData
uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic
xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr><pic:cNvPrid="0"name="frankableson.jpg"/><pic:cNvPicPr/>
</pic:nvPicPr><pic:blipFill><a:blip r:embed="rId4"
cstate="print"/><a:stretch><a:fillRect/></a:stretch>
</pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/>
<a:ext cx="3276600" cy="3838575"/></a:xfrm><a:prstGeom
prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic>
</a:graphicData></a:graphic></wp:inline></w:drawing>
</w:r></w:p><w:p w:rsidR="00663F0E" w:rsidRDefault="00663F0E"/>
<w:p w:rsidR="00CC16CE" w:rsidRDefault="00CC16CE"/><w:sectPr
w:rsidR="00CC16CE" w:rsidSect="00B6337C"><w:pgSz w:w="12240" w:h="15840"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720"
w:footer="720" w:gutter="0"/><w:cols w:space="720"/><w:docGrid
w:linePitch="360"/></w:sectPr></w:body></w:document>

XML is self-describing, but that doesn’t mean that the tags are necessarily easy to decipher. This cryptic example also demonstrates the use of multiple XML namespaces, which can make XML documents even more challenging to follow without specialized tools.

XML is everywhere, but it can often be a poor choice for an Android programmer, particularly if the data structure has fallen victim to the data explosion often associated with XML structures. A resource-constrained platform such as Android, which is usually working on a cellular data network, cannot store and parse massive amounts of XML data. However, if a particular programming task requires the interchange of both text and binary data, XML can be a solid choice.

Now you’ll look at an alternative data-interchange format: JSON.

JSON:The King of the Net

More and more Internet API providers are offering JSON as a data-format option. JSON made a name for itself in the Ajax (Asynchronous JavaScript and XML) web-programming community. Ajax technology enables web pages to update dynamically by refreshing data in selected pockets rather the entire page. Because less data is transferred—and, more important, because much less data is parsed and drawn to the browser window—an Ajax-enabled application can provide a much better user experience than a traditional web application. In fact, a well-written Ajax application can rival smart- or fat-client applications in user experience.

When an Ajax application exchanges data with a web server, it is often requesting a refresh of some kind of data, but ideally without the formatting. It is generally considered poor practice for a web server to serve up preformatted HTML. Instead, a well-written application should send data content to the browser and apply a Cascading Style Sheets (CSS) file to provide visual effects such as colors and font particulars.

Suppose an application wants to request a contact record for our mythical Mr. Mott. The application has more than one data element to send back to the browser. So how does it get packaged? In the Listing 1 example, you might use a simple request/response structure in XML. This is perfectly adequate; however, it requires that you parse each response from the server, store the data in a structure of some sort (a DOM), and then update the web page content.

Alternatively, you can simply get some JavaScript back from the server and work directly with it. Here is a sample response from a hypothetical application responding to a query (http://<yourserver/app/searchcontact?Mott) for a man named Mott. The response is a string representation of a JavaScript object; that is, a JSON string (split into two lines here to fit this article’s page width):

[{"firstname":"Troy","lastname":"Mott","age":"don't ask!"},{"firstname":"Apple seed",
   "lastname":"Mott's","age":"99"}]

Whereas XML is known for its verbosity, JSON can be a bit easier to navigate. JSON objects are constructed in a key:value pair format. The object’s elements are separated by commas, and each object is contained within curly braces {}. An array of objects is contained within square brackets. This is a common approach to transferring a series of rows from a database to an array of objects in which each array element corresponds to a database row, and each property of the object represents a column of data. If you have some JSON data that is not parsed cleanly and hard to read, browse over to jsonlint.com – this website is your friend for any work with JSON data!

Listing 3 shows an example of using this kind of object within an HTML page. For simplicity, the server communications are not included; instead, the JSON data is provided as a string variable named serverresponse.

Listing 3. Using a JSON object within an HTML page

<html>
<head>
<script language="JavaScript">
var serverresponse = "[{\"firstname\":\"Troy\",\"lastname\":\"Mott\",\"age\":\"don't
ask!\"},{\"firstname\":\"Apple seed\",\"lastname\":\"Mott's\",\"age\":\"99\"}]";
function updatepage()
{
    var contacts = JSON.parse(serverresponse );
    var i;
    var s = "Search Results:<br />";
    for (i=0;i<contacts.length;i++)
    {
        s = s + contacts[i].firstname + " " + contacts[i].lastname + "'s age is ... "
+ contacts[i].age + "<br />";
    }
    document.getElementById("target").innerHTML = s;
  }
  </script>
  </head>
  <body>
  <button onclick="updatepage();">Search for Mott</button><br />
  <span id="target"> </span>
  </body>
  </html>

Note that this example uses the JavaScript function named JSON.parse() to turn a string into a JavaScript array. Ordinarily, you will receive a JSON object directly from an AJAX call – you will not start with a literal string. The approach in Listing 3 is not a best practice. I provide it here to give some context to how a JSON object can be used in an application: The JSON structure is exchanged, parsed, and manipulated by the client code. Listing 4 provides a more typical means of acquiring and then using JSON data.

Listing 4. Using JQuery to download JSON data via an AJAX call

$.ajax( {
  "dataType": 'json', 
  "type": 'POST', 
  "url": '/someurl, 
  "data": {"q":"Mott"}, 
  "success": function(result) {
    console.log("result back from server",result);                
  }
} );

In summary, JSON is:

  • A data-interchange format.
  • A means to encode JavaScript objects as strings.
  • Limited to text and numeric values. Binary values are explicitly not permitted. JSON has no CDATAequivalent. A common approach to other types of objects is to encode them as Base64 and store them as a “string.”
  • More economical than XML in terms of data size.
  • Has become the de-factor lingua of the web.

In Listing 3 and Listing 4, the client is a web browser running client-side scripting. Returning to this article’s focus, next you’ll examine the use of XML and JSON in an Android application.

Application opportunity: Favorite book list

This article uses prefetched data from the website https://www.encouragework.com, which publishes a shares a list of popular business books in both XML and JSON formats at https://www.encouragework.com/booksxml and https://www.encouragework.com/booksjson respectively. The source of the data is https://www.encouragework.com/books.

Figure 1 shows the source of our sample data.

Figure 1. Source of our sample data
Encourage works books suggested reading

Listing 5 contains the XML snippet:

Listing 5. The XML snippet

<?xml version="1.0" encoding="UTF-8"?>
<booksxml><book>
  <title>Every Good Endeavor</title>
  <author>Timothy Keller with Katherine Leary Alsdorf</author>
  <imagelink>https://www.encouragework.com/images/uploads/everygoodendeavor.jpg</imagelink>
  <amazonlink>https://www.amazon.com/dp/1594632820/?tag=navitend-20</amazonlink>
</book><book>
  <title>The 7 Habits of Highly Effective People</title>
  <author>Stephen Covey</author>
  <imagelink>https://www.encouragework.com/images/uploads/7habits.jpg</imagelink>
  <amazonlink>https://www.amazon.com/dp/1451639619/?tag=navitend-20</amazonlink>
</book><book>
  <title>Traction</title>
  <author>Gino Wickman</author>
  <imagelink>https://www.encouragework.com/images/uploads/tractionfront.jpg</imagelink>
  <amazonlink>https://www.amazon.com/dp/1936661837/?tag=navitend-20</amazonlink>
</book><book>
  <title>Get a Grip</title>
  <author>Gino Wickman and Bill Paton</author>
  <imagelink>https://www.encouragework.com/images/uploads/getagripfront.jpg</imagelink>
  <amazonlink>https://www.amazon.com/dp/1939529824/tag=navitend-20</amazonlink>
</book><book>
  <title>Mastering the Rockefeller Habits</title>
  <author>Verne Harnish</author>
  <imagelink>https://www.encouragework.com/images/uploads/rockefellerhabits.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Mastering-Rockefeller-Habits-Increase-Growing/dp/0978774957/?tag=navitend-20</amazonlink>
</book><book>
  <title>Scaling Up</title>
  <author>Verne Harnish</author>
  <imagelink>https://www.encouragework.com/images/uploads/scalingup.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Scaling-Up-Companies-Rockefeller-Habits/dp/0986019526/?tag=navitend-20</amazonlink>
</book><book>
  <title>Good To Great</title>
  <author>Jim Collins and Jerry Porras</author>
  <imagelink>https://www.encouragework.com/images/uploads/goodtogreat.jpg</imagelink>
  <amazonlink>https://www.amazon.com/dp/0066620996/?tag=navitend-20</amazonlink>
</book><book>
  <title>Scrum</title>
  <author>Jeff Southerland</author>
  <imagelink>https://www.encouragework.com/images/uploads/scrum.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Scrum-Doing-Twice-Work-Half/dp/038534645X/?tag=navitend-20</amazonlink>
</book><book>
  <title>The Goal</title>
  <author>Eli Goldratt</author>
  <imagelink>https://www.encouragework.com/images/uploads/thegoal.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0884271951/?tag=navitend-20</amazonlink>
</book><book>
  <title>It’s Not Luck</title>
  <author>Eli Goldratt</author>
  <imagelink>https://www.encouragework.com/images/uploads/itsnotluck.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Its-Not-Luck-Eliyahu-Goldratt/dp/0884271153/?tag=navitend-20</amazonlink>
</book><book>
  <title>Critical Chain</title>
  <author>Eli Goldratt</author>
  <imagelink>https://www.encouragework.com/images/uploads/criticalchain.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Critical-Chain-Eliyahu-M-Goldratt/dp/0884271536/?tag=navitend-20</amazonlink>
</book><book>
  <title>The Phoenix Project</title>
  <author>Gene Kim, Kevin Behr, and Gene Spafford</author>
  <imagelink>https://www.encouragework.com/images/uploads/phoenixproject.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262509/?tag=navitend-20</amazonlink>
</book><book>
  <title>Mathematics: Is God Silent?</title>
  <author>James Nickel</author>
  <imagelink>https://www.encouragework.com/images/uploads/mathisgodsilent.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Mathematics-God-Silent-James-Nickel/dp/187999822X/?tag=navitend-20</amazonlink>
</book><book>
  <title>Men of Mathematics</title>
  <author>E.T. Bell</author>
  <imagelink>https://www.encouragework.com/images/uploads/menofmath.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Mathematics-Touchstone-Book-E-T-Bell/dp/0671628186/?tag=navitend-20</amazonlink>
</book><book>
  <title>God and Money</title>
  <author>John Cortines and Gregory Baumer</author>
  <imagelink>https://www.encouragework.com/images/uploads/godandmoney.jpg</imagelink>
  <amazonlink>https://www.amazon.com/God-Money-Discovered-Business-Paperback/dp/1628624736/?tag=navitend-20</amazonlink>
</book><book>
  <title>Profit First</title>
  <author>Mike Michalowicz</author>
  <imagelink>https://www.encouragework.com/images/uploads/profitfirst.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Profit-First-Transform-Cash-Eating-Money-Making/dp/073521414X/?tag=navitend-20</amazonlink>
</book><book>
  <title>Updraft</title>
  <author>Jackie Freedman</author>
  <imagelink>https://www.encouragework.com/images/uploads/updraft.jpg</imagelink>
  <amazonlink>https://www.amazon.com/Updraft-Aerodynamics-Leadership-Jacquelyn-Freedman/dp/0986156035/tag=navitend-20</amazonlink>
</book></booksxml>

Listing 6 shows the same data, this time in JSON format:

Listing 6. Feed data in JSON format

    {
        "title": "Every Good Endeavor",
        "author": "Timothy Keller with Katherine Leary Alsdorf",
        "imagelink": "https://www.encouragework.com/images/uploads/everygoodendeavor.jpg",
        "amazonlink": "https://www.amazon.com/dp/1594632820/?tag=navitend-20"
    },

    {
        "title": "The 7 Habits of Highly Effective People",
        "author": "Stephen Covey",
        "imagelink": "https://www.encouragework.com/images/uploads/7habits.jpg",
        "amazonlink": "https://www.amazon.com/dp/1451639619/?tag=navitend-20"
    },

    {
        "title": "Traction",
        "author": "Gino Wickman",
        "imagelink": "https://www.encouragework.com/images/uploads/tractionfront.jpg",
        "amazonlink": "https://www.amazon.com/dp/1936661837/?tag=navitend-20"
    },

    {
        "title": "Get a Grip",
        "author": "Gino Wickman and Bill Paton",
        "imagelink": "https://www.encouragework.com/images/uploads/getagripfront.jpg",
        "amazonlink": "https://www.amazon.com/dp/1939529824/tag=navitend-20"
    },

    {
        "title": "Mastering the Rockefeller Habits",
        "author": "Verne Harnish",
        "imagelink": "https://www.encouragework.com/images/uploads/rockefellerhabits.jpg",
        "amazonlink": "https://www.amazon.com/Mastering-Rockefeller-Habits-Increase-Growing/dp/0978774957/?tag=navitend-20"
    },

    {
        "title": "Scaling Up",
        "author": "Verne Harnish",
        "imagelink": "https://www.encouragework.com/images/uploads/scalingup.jpg",
        "amazonlink": "https://www.amazon.com/Scaling-Up-Companies-Rockefeller-Habits/dp/0986019526/?tag=navitend-20"
    },

    {
        "title": "Good To Great",
        "author": "Jim Collins and Jerry Porras",
        "imagelink": "https://www.encouragework.com/images/uploads/goodtogreat.jpg",
        "amazonlink": "https://www.amazon.com/dp/0066620996/?tag=navitend-20"
    },

    {
        "title": "Scrum",
        "author": "Jeff Southerland",
        "imagelink": "https://www.encouragework.com/images/uploads/scrum.jpg",
        "amazonlink": "https://www.amazon.com/Scrum-Doing-Twice-Work-Half/dp/
          038534645X/?tag=navitend-20"
    },

    {
        "title": "The Goal",
        "author": "Eli Goldratt",
        "imagelink": "https://www.encouragework.com/images/uploads/thegoal.jpg",
        "amazonlink": "https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0884271951/
           ?tag=navitend-20"
    },

    {
        "title": "It’s Not Luck",
        "author": "Eli Goldratt",
        "imagelink": "https://www.encouragework.com/images/uploads/itsnotluck.jpg",
        "amazonlink": "https://www.amazon.com/Its-Not-Luck-Eliyahu-Goldratt/dp/0884271153/
          ?tag=navitend-20"
    },

    {
        "title": "Critical Chain",
        "author": "Eli Goldratt",
        "imagelink": "https://www.encouragework.com/images/uploads/criticalchain.jpg",
        "amazonlink": "https://www.amazon.com/Critical-Chain-Eliyahu-M-Goldratt/dp/0884271536/
           ?tag=navitend-20"
    },

    {
        "title": "The Phoenix Project",
        "author": "Gene Kim, Kevin Behr, and Gene Spafford",
        "imagelink": "https://www.encouragework.com/images/uploads/phoenixproject.jpg",
        "amazonlink": "https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262509/?tag=navitend-20"
    },

    {
        "title": "Mathematics: Is God Silent?",
        "author": "James Nickel",
        "imagelink": "https://www.encouragework.com/images/uploads/mathisgodsilent.jpg",
        "amazonlink": "https://www.amazon.com/Mathematics-God-Silent-James-Nickel/dp/187999822X/
           ?tag=navitend-20"
    },

    {
        "title": "Men of Mathematics",
        "author": "E.T. Bell",
        "imagelink": "https://www.encouragework.com/images/uploads/menofmath.jpg",
        "amazonlink": "https://www.amazon.com/Mathematics-Touchstone-Book-E-T-Bell/dp/0671628186/?tag=navitend-20"
    },

    {
        "title": "God and Money",
        "author": "John Cortines and Gregory Baumer",
        "imagelink": "https://www.encouragework.com/images/uploads/godandmoney.jpg",
        "amazonlink": "https://www.amazon.com/God-Money-Discovered-Business-Paperback/dp/1628624736/?tag=navitend-20"
    },

    {
        "title": "Profit First",
        "author": "Mike Michalowicz",
        "imagelink": "https://www.encouragework.com/images/uploads/profitfirst.jpg",
        "amazonlink": "https://www.amazon.com/Profit-First-Transform-Cash-Eating-Money-Making/dp/073521414X/?tag=navitend-20"
    },

    {
        "title": "Updraft",
        "author": "Jackie Freedman",
        "imagelink": "https://www.encouragework.com/images/uploads/updraft.jpg",
        "amazonlink": "https://www.amazon.com/Updraft-Aerodynamics-Leadership-Jacquelyn-Freedman/dp/0986156035/tag=navitend-20"
    }

In our sample application, we will parse these data structures and extract the title and author fields. Next, I’ll show you the pertinent portions of an Android application that parses this data. The full project is available for download from my GitHub repo.

The BOOKS application

The Android application is simple. It contains full copies of the XML and JSON data feeds and gives the user the option of parsing either one. Figure 2 shows the structure of the project files within Android Studio.

Figure 2. File structure listing books in both xml and json formats
File structure listing books in both xml and json formats

Figure 3 shows the application’s UI prior to the selection of a parsing option:

Figure 3. The application’s UI prior to selection of a parsing option
Screen capture of the application's user interface prior to selecting a parsing option

The application UI shows two buttons, XML and JSON, followed by instructional text. Listing 7 contains the layout for this UI, found in the activity_main.xml file in the res/layout folder of the project:

Listing 7. The layout for the UI

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="vertical"
    tools:context="com.navitend.books.MainActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:orientation="horizontal"
        tools:context="com.navitend.books.MainActivity">

        <Button
            android:id="@+id/parseXML"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="XML" />

        <Button
            android:id="@+id/parseJSON"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="JSON" />
    </LinearLayout>

    <TextView
        android:id="@+id/tvData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:text="Select a Button to Proceed" />

</LinearLayout>

The XML and JSON buttons are defined along with a TextView for displaying our results.

Note the use of multiple LinearLayout structures. The first is a vertical alignment, and it contains both a LinearLayout with a horizontal TextView. The inner LinearLayout contains the two Button widgets. This layout is inflated and wired up in the onCreate() method, shown in Listing 8.

Listing 8. The onCreate() method

Button btnXML;
Button btnJSON;
TextView tvData;
String TAG = this.getClass().getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnXML = (Button) findViewById(R.id.parseXML);
    btnJSON = (Button) findViewById(R.id.parseJSON);
    tvData = (TextView) findViewById(R.id.tvData);
    tvData.setMovementMethod(new ScrollingMovementMethod());


    btnXML.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {
            Log.i(TAG,"XML Clicked");
            tvData.setText("attempt to parse XML");
            examineXMLFile();
        }
    });

    btnJSON.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {
            Log.i(TAG,"JSON Clicked");
            tvData.setText("attempt to parse JSON");
            examineJSONFile();
        }
    });


}

The examineXMLFile() method controls the XML parsing.

XML parsing

The parsing of XML data is often done with a SAX-style parser. With this style of parser, you set up an InputSource pointing to the source XML data and provide a handler that receives certain events as the document is “walked.” Listing 9 shows the examineXMLFile() method, which takes care of the following tasks:

  • Sets up the InputSource with the XML file from the raw resources
  • Creates a SAXParser, associated with a handler named bookshandler (in Listing 10)
  • Invokes the parser and displays the results in a TextView widget identified in the layout file as R.id.tvData and referenced in the code as tvData
  • Shows any errors in the LogCat window

Listing 9. The examineXMLFIle() method

void examineXMLFile() {
    try {
        Log.i(TAG,"Beginning examination of XML data");
        InputSource is = new InputSource(getResources().openRawResource(R.raw.booksxml));

        // create the factory
        SAXParserFactory factory = SAXParserFactory.newInstance();

        // create a parser
        SAXParser parser = factory.newSAXParser();

        // create the reader (scanner)
        XMLReader xmlreader = parser.getXMLReader();

        // instantiate our handler
        bookshandler bh = new bookshandler();

        // assign our handler
        xmlreader.setContentHandler(bh);

        // perform the synchronous parse
        xmlreader.parse(is);

        // should be done... let's display our results
        tvData.setText(Html.fromHtml(bh.getResults()));

    } catch (Exception e) {
        Log.e(TAG, "Error parsing XML data " + e.getMessage());
    }
}

Whereas examineXMLFile() sets things up, the real parsing work from the perspective of the application takes place in the handler that’s implemented in the bookshandler.java file. This class, which implements the DefaultHandler interface, is in Listing 10:

Listing 10. The bookshandler class

/*
 *
 * fableson@navitend.com
 *
 */

package com.navitend.books;

import android.util.Log;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;



public class bookshandler extends DefaultHandler {

    StringBuilder sb = null;
    String ret = "";
    boolean bStore = false;
    int howMany = 0;


    bookshandler() {
    }

    String getResults()
    {
        return "<p>Books from<br>https://www.encouragework.com/books</p><p>There are [" + howMany + "] books:</p>" + ret;
    }
    @Override

    public void startDocument() throws SAXException {
        // initialize "list"
    }

    @Override
    public void endDocument() throws SAXException {

    }

    @Override
    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) 
            throws SAXException {

        try {
            if (localName.equals("book")) {
                this.sb = new StringBuilder("");
                bStore = false;
            }
            if (localName.equals("title") || localName.equals(("author"))) {
                bStore = true;
            }
        } catch (Exception ee) {

            Log.d("error in startElement", ee.getStackTrace().toString());
        }
    }



    @Override

    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {

        if (bStore) {
            if (localName.equals("title")) {
                ret += "<u>" + sb.toString() + "</u><br>";
                sb = new StringBuilder("");
                return;

            }

            if (localName.equals("author")) {
                ret += "by:" + sb.toString() + "<br/><br/>";
                sb = new StringBuilder("");
                return;

            }

        }
        if (localName.equals("book")) {
            howMany++;
            bStore = false;
        }
    }


    @Override

    public void characters(char ch[], int start, int length) {

        if (bStore) {
            String theString = new String(ch, start, length);

            this.sb.append(theString);
        }
    }

}

Listing 10 contains some noteworthy items. The first thing to consider is that the SAX parser is an event-based parser, which means that you build the actual document as it is parsed. Events are fired whenever the document starts, the document ends, a tag starts, a tag ends, and data is found. This implies that you must define a data structure to keep the data of interest and discard the rest. Note the StringBuilder and the appending of data, used because a particular data element can be processed across multiple reads on the InputSource. Never assume that all of the data is provided in any given call to the characters() method.

This application collects the data into a simply formatted string. An alternative example might include putting these entries into a collection class or database instead, particularly if a great deal of manipulation were to take place after the parse.

The getResults() method is custom to this class. It’s used to gather the assembled representation of this data and provide it to the application. It is not part of the DefaultHandler's interface. The results of the XML parsing are formatted with some minimalist HTML.

Figure 4 depicts the parsed XML data.

Figure 4. The parsed XML data
Screen capture of the parsed XML data on a mobile phone screen

Although parsing XML with the SAX parser is nontrivial in terms of building up, managing, and navigating the resulting structure, its main advantages are speed and the opportunity to reduce significantly the amount of RAM required both during and after the parsing step.

Now you’ll take a look at Android’s approach to parsing JSON data.

JSON parsing

Parsing JSON data in the application starts when the user selects the JSON button. This invokes the examineJSONFile() method, in Listing 11. No additional handler class is required, because all parsing and document management take place within the Android-supplied libraries, and all JSON-related code is contained in this method.

Listing 11. Invoking the examineJSONfile() method

void examineJSONFile()
{
    try
    {
        Log.i(TAG,"Beginning examination of JSON data");
        String x = "";
        InputStream is = this.getResources().openRawResource(R.raw.booksjson);
        byte [] buffer = new byte[is.available()];
        while (is.read(buffer) != -1);
        String jsontext = new String(buffer);
        JSONArray entries = new JSONArray(jsontext);

        x = "encouraggework.com book list in JSON parsed.\nThere are [" + entries.length() + "] books\n\n";

        int i;
        for (i=0;i<entries.length();i++)
        {
            JSONObject book = entries.getJSONObject(i);
            x += "------------\n";
            x += "Title:" + book.getString("title") + "\n";
            x += "Author:" + book.getString("author") + "\n\n";
        }
        tvData.setText(x);
    }
    catch (Exception je)
    {
        tvData.setText("Error w/file: " + je.getMessage());
    }
}

Like the XML routine shown previously, this code reads in a file from the raw resources. The data is read into memory in its entirety, converted to a java.lang.String, and then parsed into a JSONArray. Note that a particular string can be parsed directly into an array, as in this example, or the string can be parsed into a JSONObject. Because the Book data is an array of objects, it makes sense to parse the entire string into an array and then access the object individually by ordinal position.

This method’s flow is straightforward; once the data is parsed, the code builds up a string representation that’s similar to the approach of the XML parser handler. Of interest here is that the data is managed for you; you don’t need to build up additional memory structures to contain the data. Likewise, the application knows up front just how many entries are in the JSONArray (17 in this example).

Figure 5 shows the output from the JSON parsing. Note that this is just a simple text string – no HTML formatting going on here, just to change things up a bit.

Figure 5. JSON output
Screen capture of the parsed XML data on a mobile phone screen

Although JSON parsing is much more simple programmatically, it is not cost-free. It adds the burden of memory consumption for reading in the entire data stream before it can be worked on, and for storing all of the data. In contrast, the SAX XML approach uses only the data of interest. That caveat aside, if memory for parsing a particular JSON object is ample, this approach can be favorable for many applications, particularly if working with the DOM is of little interest.

Conclusion

This article introduced XML and JSON data-interchange formats in the context of an Android application. Compared to the JSON approach, the XML approach is somewhat faster and less memory-constrained—at the expense of additional complexity. In Part 2, “Deliver hybrid Android applications with JSON,” I’ll introduce some advanced techniques combining JSON data, WebKit-based WebView widgets, and custom dynamic application logic for Android applications.