Complete XML reading/parsing on Android Tutorial

Android xml

In the following tutorial, I will demonstrate how to read and parse XML in your Android app.

for this example, I will use the following XML infoset:

myxml.xml

1
Hello World!
Hello World!

 

Saving the XML inside your android project

you can save your XML file either in the res/ folder, or the assets/ folder of your project:
Both are pretty similar. The real main difference between the two is that in the res directory is pre-compiled, so each file is given an id which can be accessed easily through R.id.[res id].

The assets directory is provides more freedom to put any file you would like in there. You then can access each of the files in that system as you would when accessing any file in any file system through Java.

  • With resources, there’s built-in support for providing alternatives for different languages, OS versions, screen orientations, etc., None of that is available with assets.
  • The R-class indexes all resources and provides simple access for the res/ folder. There are some simple methods which help reading files stored in the res-directory. No indexing by the R-class for the assets/ directory
  • No subdirectorys are allowed under the res/ folders. Subdirectorys are allowed (as much as you like) for the assets/ folder.
  • you really can’t edit files directly or add new files to either at runtime. You will need to work with files on either internal or external storage to do those things.

if you choosed the res/ folder, you can place the xml in the res/xml folder, or in the res/raw folder:

  • res/xml/ – Arbitrary XML files that are compiled and can be read at run time by calling Resources.getXML().
  • res/raw/ – Arbitrary files to copy directly to the device. They are added uncompiled to the compressed file that your application build produces. To use these resources in your application, call Resources.openRawResource() with the resource ID, which is R.raw.somefilename.

get from res/xml:

1
XmlResourceParser xrp = getResources().getXml(R.xml.myxml);
XmlResourceParser xrp = getResources().getXml(R.xml.myxml);

get from assets/:

1
InputStream is = getAssets().open("myxml.xml");
InputStream is = getAssets().open("myxml.xml");

get from res/raw:

1
InputStream is = getResources().openRawResource(R.raw.myxml);
InputStream is = getResources().openRawResource(R.raw.myxml);

get from URL:

you can also get your XML from an online server:

1
InputStream is = new URL(Url).openConnection().getInputStream();
InputStream is = new URL(Url).openConnection().getInputStream();

Note that getXml() is the only function that returns XmlResourceParser class and not InputStream class. It’s matters later, when you come to parse that XML.
In res/ folder all xml files are precompiled, whereas in assets/ folder they are not. So, you can’t use openXmlResourceParser() with non-precompiled resources.


 

Validating Schema

altough, I am not going to discuss validating and schema in this article, you should validate the XML before parsing it. read more here. It’s strongly adviced to use schema for your xml-infoset.


 

Parsing XML

There are two models for parsing XML: document streaming and the DOM. You can read
more on this subject here. most of Java’s XML-related APIs are fully supported on Android.

Android comes loaded with lots of tools for dealing with XML. You can pick just one of these as your tool-of-choice, or you can pick and choose based on the use case:

  • Pull parser
  • Java’s Simple API for XML (SAX) parser
  • Document Object Model (DOM) parser

all the parsers can work with InputStream. XmlResourceParser is a Pull-parser extension, so using getXml() will return a Pull-parser by design.
The Streaming API for XML (StAX) and Java XML Binding API are not available in Android.

What to choose?

It’s depend on your needs,
Most of the time the safe pick is to go with SAX. It probably looks a bit more intimidating to use than the DOM or Pull parser, but it’s a lot faster. the code may look longer sometimes, but it’s more clearer code then DOM or Pull-parser.
If your document is very simple, or if your document is large, but you only need part of the document, then the XML pull parser might be a more efficient way to go.
as DOM is lack in terms of CPU and Memory efficiency, it’s qualities are XPath Capability, Update XML at parsing and is the only one that enables you to go ‘Backward’ and not ‘Forward Only’ as SAX and Pull-parser.

Note

before you continue, at this point, it’s important to mention that you should handle each parser differently with the different XML sources.
for example, if your XML located at res/xml, your probably using getResources().getXml(id) to get it’s content, which as mentioned earlier, returns an XmlResourceParser object which extends XmlPullParser class, which means you get by default a pull-parser from getXml().
with SAX parser, in this case, you will have a ‘harder’ case because it’s constructor accept InputStream object.

Pratically,

 

Pull parser implementation

I’ll demonstrate you the pull parser implemntation using local resource (res/xml/myxml.xml), which is very simple. more implementations may be published later.

Inside your activity/service:

the following example move over the xml file and log it’s content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    private void getXMLfromResource() throws IOException, XmlPullParserException {
        // Create ResourceParser for XML file
        XmlResourceParser xpp = getResources().getXml(R.xml.myxml);
        // check state
        int eventType = xpp.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
          // instead of the following if/else if lines
          // you should custom parse your xml
          if(eventType == XmlPullParser.START_DOCUMENT) {
              System.out.println("Start document");
          } else if(eventType == XmlPullParser.START_TAG) {
              System.out.println("Start tag "+xpp.getName());
          } else if(eventType == XmlPullParser.END_TAG) {
              System.out.println("End tag "+xpp.getName());
          } else if(eventType == XmlPullParser.TEXT) {
              System.out.println("Text "+xpp.getText());
          }
          eventType = xpp.next();
        }
        // indicate app done reading the resource.
        xpp.close();
    }
	private void getXMLfromResource() throws IOException, XmlPullParserException {
		// Create ResourceParser for XML file
		XmlResourceParser xpp = getResources().getXml(R.xml.myxml);
        // check state
		int eventType = xpp.getEventType();
		while (eventType != XmlPullParser.END_DOCUMENT) {
          // instead of the following if/else if lines
          // you should custom parse your xml
		  if(eventType == XmlPullParser.START_DOCUMENT) {
		      System.out.println("Start document");
		  } else if(eventType == XmlPullParser.START_TAG) {
		      System.out.println("Start tag "+xpp.getName());
		  } else if(eventType == XmlPullParser.END_TAG) {
		      System.out.println("End tag "+xpp.getName());
		  } else if(eventType == XmlPullParser.TEXT) {
		      System.out.println("Text "+xpp.getText());
		  }
		  eventType = xpp.next();
		}
    	// indicate app done reading the resource.
    	xpp.close();
	}

There are two key methods available in xpp: .next() and .nextToken(). While next() provides access to high level parsing events, nextToken() allows access to lower level tokens.
The method nextToken() works similarly to next() but will expose additional event types (COMMENT, CDSECT, DOCDECL, ENTITY_REF, PROCESSING_INSTRUCTION, or IGNORABLE_WHITESPACE) if they are available in input.

the example function throws IOException because xpp.next() throws it, and XmlPullParserException because xpp.getEventType() throws it. you should trap them in your app like:

1
2
3
4
5
6
7
8
9
        try {
            getXMLfromResource();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
        	getXMLfromResource();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

which returns for our xml example:

1
2
3
4
Start document
Start tag foo
Text Hello World!
End tag foo

More on the subject

External libraries

after you done, and you are parsing your XML using android APIs, you may learn to use external API. There are many external libraries to handle xml infosets as:

check them, and others, if they suit your needs. some of them help you parse, some are for direct mapping between a class to an xml. every class has it’s pros and cons. learn them.

 

And remember, XML is like violence – If it doesn’t solve your problem, you’re not using enough of it!


Portions of this page are reproduced from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License. Android is a trademark of Google Inc.

Development Specialist, Artist and Activist
Personal Website

3 thoughts on “Complete XML reading/parsing on Android Tutorial

Leave a Reply

Your email address will not be published.


*