Wednesday, July 14, 2010

Reading Android XML Resources

I’ve been playing recently with some Android development and recently I needed to load an XML resource (for API 3). I was very surprised to find that Android doesn’t have a super easy way of loading XML resource files.

The XMLPullParser works but it’s very bare metal and does leave quite a bit to be desired. So I decided to go ahead and create a generic XML parser that all android developers can use (and improve).




public class XMLData {
    public String mValue;
    public XMLData mParent;
    public List mChild;
   
    public XMLData(String value, XMLData parent) {
        mParent = parent;
        mChild = new ArrayList();
        mValue = value;
    }
}   



First we establish a base XML data structure I decided to keep things simple here so I'm not at all doing anything about attributes if you wish to handle attributes you need to add a new ArrayList for attributes.

Now that we have our basic XML data type we can start create a class to read it:


    public static XMLData Load(XmlPullParser parser) {
        XMLData xmlModel = null;
        XMLData currentNode = null;
       
        try
        {
            int eventType = parser.getEventType();
           
            while (eventType != XmlPullParser.END_DOCUMENT){
                String name = null;
                    switch (eventType)    {
                        case XmlPullParser.START_DOCUMENT:
                            xmlModel = new XMLData("root", null);
                            currentNode = xmlModel;
                            break;
                        case XmlPullParser.START_TAG:
                            name = parser.getName();
                           
                            if (name != null) {
                                XMLData dataNode = new XMLData(name, currentNode);
                                currentNode.mChild.add(dataNode);
                                currentNode = dataNode;
                            }
                            break;
                           
                        case XmlPullParser.TEXT:
                            name = parser.getText();
                           
                            if (name != null) {
                                XMLData fieldNode = new XMLData(name,currentNode);
                                currentNode.mChild.add(fieldNode);
                            }
                            break;
                           
                        case XmlPullParser.END_TAG:
                            name = parser.getName();
                           
                            currentNode = currentNode.mParent;
                            break;
                    }
                   
                    eventType = parser.next();
            }
        } catch (XmlPullParserException e) {
            Log.e("ParseEx", e.getMessage());
        } catch (IOException e) {
            Log.e("IOEx", e.getMessage());
        }
       

        return xmlModel;
    }



So let's back up for a second and look at what this does. We start off by first executing:

int eventType = parser.getEventType();

This reads off our first tag for the XMLPullParser.what follows is the main while loop.

There are 4 Major event types we are concerned with:

XmlPullParser.START_DOCUMENT
XmlPullParser.END_DOCUMENT
XmlPullParser.START_TAG
XmlPullParser.END_TAG
XmlPullParser.TEXT

START_DOCUMENT and END_DOCUMENT denote the beginning and end of the document when we get a start we concern ourselves with initializing the XMLData so we can start to build an XML tree.

START_TAG and END_TAG denote when each of the tags expand. On a START_TAG we prepare ourselves to traverse into the ENTRY by creating a new XMLData.


 case XmlPullParser.START_TAG:
             name = parser.getName();
                            
             if (name != null) {
                XMLData dataNode = new XMLData(name, currentNode);
                currentNode.mChild.add(dataNode);
                currentNode = dataNode;
             }
             break;



dataNode in this case is the newly created node ready for traversal. We then perform currentNode = dataNode remember that we are now traversing down the node.

On END_TAG we do one and only one thing we go up one level from our tree structure. This is accomplished with the following code:


         case XmlPullParser.END_TAG:
            name = parser.getName();
                           
            currentNode = currentNode.mParent;
            break;



Finally we have TEXT in which we read off the actuall data of an element:


     case XmlPullParser.TEXT:
         name = parser.getText();

                   
         if (name != null) { 

             XMLData fieldNode = new XMLData(name,currentNode);
             currentNode.mChild.add(fieldNode);
         }
         break;




Hopefully this tutorial breaks down an easy way to access your XML data. If you want to use XMLData right away you can grab it here! I haven't decided what license I'll release it under but I'm thinking it'll be under the same license as Google SDK.

DOWNLOAD SOURCE

No comments: