How to parse XML, RSS feed with kXML in a J2ME MIDlet

7 comments - This post in romanian

More an more mobile devices are used to access Internet and connected services. One efficient way to transfer data between different platforms and technologies is to use XML files, which are simple text files formatted accordingly to the XML rules.

IN order to process an XML file and to extract needed data you need a XML parser which is a text process engine.

The problem for J2ME MIDlets is that there are mobile devices that don’t support the XML API for Java ME additional package (JSR 280). In order to solve this problem, we need an independent and lightweight XML parser that must be fast and with a small impact on the memory. Two possible solutions are kXML and NanoXML.

In the next MIDlet example (You can download the full source code, including a sample test MIDlet), we will use kXML to parse a RSS feed, the itcsolutions.eu RSS feed.

How to use kXML

In order to understand how to:

check How to use kXML to parse XML files in J2ME projects post.

How to access a Web based XML document from a MIDlet

In order to access a XML document on the Web, we need a HttpConnection object. Once we get an active connection, we can process the XML at byte or char level.

For processing the remote XML at char level, we need an InputStreamReader (it will be created based on the InputStream object). This will be the input for the kXML parser.

Because operations that require network access can block the main thread, the entire procedure of getting the XML file from the given URL and parsing it, will be executed in a secondary thread. This will prevent the application to block and it will allow users to use the application commands like Exit. Other wise, the main thread will wait for the network operation to end in order to execute command handlers.

The method that handles the HTTP connection is getXMLFeed():

public void getXMLFeed(final String url) {
    Thread t = new Thread() {
        public void run() {
            HttpConnection myConnection = null;
            try {
                //open the connection
                myConnection = (HttpConnection) Connector.open(url);
		//get the bytes stream
                InputStream stream = myConnection.openInputStream();
		//call the parsing method
                ParseXMLFeed(stream);
            } catch (Exception error) {
                parentMidlet.DisplayError(error);
            } finally {
                //close the connection
                try {
                    if (myConnection != null) {
                        myConnection.close();
                    }
                } catch (IOException eroareInchidere) {
		//calls a method from the MIDlet that display an alert
                    parentMidlet.DisplayError(eroareInchidere);
                }
            }
        }
    };
    //starts the thread
    t.start();
}

How to parse the RSS feed using the kXML parser

In order to use the kXML parser you must:

The method that implements the XML parsing is ParseXMLFeed():

  • the method argument is an InputStream reference; this will be used to create a Reader reference needed to process the XML at char level and also needed to define the input for the kXmlParser.
  • the method extracts only the title and the link for each RSS item; the data is stored in a News (class defined in the utility package) item; the News item is added in a Vector defined at MIDlet level using the midlet addNews() method;

The steps that define the process of parsing the XML feed are:

  1. create and initialize the KXmlParser using the InputStreamReader provided by the HttpConnection;
  2. because the <item> nodes are sub-nodes of <channel> and we want to process them in a iterative way, we must go past <rss> into <channel> sub-nodes collection;
  3. loop through the nodes using nextTag() method and for each <item> start tag, get the title and the link; the title and the link are used to create a News object that is added to the Vector collection of the Midlet;
  4. for any other node than <item> skip it and its details using skipSubTree() method;
  5. when we reach a <channel> node, it means we have finished its sub-tree because this is the end tag;
private void ParseXMLFeed(InputStream input)
        throws IOException, XmlPullParserException {
    Reader dataReader = new InputStreamReader(input);
 
    //kXML parser
    KXmlParser myParser = new KXmlParser();
    myParser.setInput(dataReader);
 
    //skip the first node - rss
    myParser.nextTag();
    myParser.require(XmlPullParser.START_TAG, null, "rss");
    //skip the second node - channel
    myParser.nextTag();
    myParser.require(XmlPullParser.START_TAG, null, "channel");
    myParser.nextTag();
    myParser.require(XmlPullParser.START_TAG, null, "title");
 
    while (myParser.getEventType() != XmlPullParser.END_DOCUMENT) {
        String name = myParser.getName();
        //this is for reaching the end tag for channel node
        if (name.equals("channel")) {
            break;
        }
        //this is for each item node in the RSS feed
        if (name.equals("item")) {
            //process it only if it is reached the start tag
            if (myParser.getEventType() != XmlPullParser.END_TAG) {
                myParser.nextTag();
                String title = myParser.nextText();
                myParser.nextTag();
                String link = myParser.nextText();
 
                //create a new News item
                News news = new News(title, link);
                parentMidlet.addNews(news);
            }
        } else {
            //if it is not the item node the skip it and all its details
            myParser.skipSubTree();
        }
        //move to the next tag
        myParser.nextTag();
    }
    //close the input stream - job done
    input.close();
}

How is working the mobile application

  • the application is managing the RSS feed items (only the title and the link) using a Vector collection of News objects, news;
  • the title of each News object is displayed in a List type form, myNewsList;
  • in order to add elements to the Vector collections, the MIDlet provide a public method addNews(); the method also set the List form, myNewsList, as the current one;
//method called by the parsing thread
public void addNews(News newsItem){
    news.addElement(newsItem);
    myNewsList.append(newsItem.getTitle(),null);
    myDysplay.setCurrent(myNewsList);
}
  • the application has 2 commands: one for closing the application, cmdExit, and one, cmdDetails, for displaying in a Alert details (the link) of the selected title;
public void commandAction(Command command, Displayable displayable) {
    if(command == cmdExit){
        destroyApp(false);
        notifyDestroyed();
    } else
        if(command == cmdDetails || command == List.SELECT_COMMAND){
        //get the index of the selected title
        int index = myNewsList.getSelectedIndex();
        if(index!=-1) {
            //get the Vector element at that index - News object
            News newsItem = (News)news.elementAt(index);
 
            //display the link in an Alert
            Alert message = new Alert(newsItem.getTitle(),
                    newsItem.getLink(),
                    null,
                    null);
            message.setTimeout(Alert.FOREVER);
            myDysplay.setCurrent(message,myNewsList);
 
        } else
            return;
        }
}

the MIDlet has 2 threads; the main one which is used to display the List form and to manage the 2 commands; the second thread implements the parsing process; the second thread starts when the getXMLFeed() method is called;

    public void startApp() {
        myNewsList.setCommandListener(this);
 
        //the XML file url
        String url = "http://www.itcsolutions.eu/feed/";
 
        ParseThread myThread = new ParseThread(this);
        //this will start the second thread
        myThread.getXMLFeed(url);
 
        Display.getDisplay(this).setCurrent(myNewsList);
    }

The main screens of the MIDlet are:

RSS titles list

RSS titles list

RSS title details

RSS title details

You can download the full source code, including a sample test MIDlet.

, ,


  1. #1 by Ratnesh on August 28th, 2011

    Well i am trying to build this application but i am facing some problem . I am getting exception ¨Uncaught Exception java/lang/NoClassDefFoundError: org/kxml2/io/KXmlParser¨

    i had used Kxml2 jar … I need help urgently.

    • #2 by Catalin on August 29th, 2011

      Hi Ratnesh,

      Have you added the kxml library to your J2ME project ? If yes, have you downloaded and tested the sample application from the post ?

      If the sample application is working but not your project please show me the import statements and the statement that generates the error.

  2. #3 by Andre on September 4th, 2011

    Hi, Please can you assist me in my project, i am building a J2ME application that has a news, forex and weatherapps in one midlet, i intend using your Rss feed example for the news area, i hav eused the VMD as the main form and i will want to link it to your sample midlet but in the sam eproject, how do i link them?
    Thanks

    • #4 by Catalin on September 10th, 2011

      Hi Andre,

      It is simple to import the code sample into your project:
      1. download and open the zip archive
      2. copy the 2 files from the \eu\itcsolutions\rssparser\utility folder into your project directory
      3. edit the 2 files and change the package name based on your own package structure (modify the package eu.itcsolutions.rssparser.utility; declaration)
      4. as you already have a Midlet, create a new class that extends List and copy most of the XMLMidlet.java in the new class (code from startApp() can go in the class constructor)

      If you still have problems, I can give you the class from step 4.

  3. #5 by Tung on October 17th, 2011

    Hi, i make a j2me app, it runs very well but when i built with obfuscate, it cannot get data from internet.

(will not be published)