How to use kXML to parse XML files in J2ME projects

4 comments - This post in romanian

kXML is a small XML pull parser, specially designed for constrained environments such as Applets, Personal Java or MIDP devices.

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.

To see a full example of J2ME MIDlet that is using kXML to parse XML RSS feed, check How to parse XML, RSS feed with kXML in a J2ME MIDlet

kXML methods description

One problem with the kXML parser is that its documentation is pore and it doesn’t provide detailed description on its methods.

Let’s consider the next XML:

<?xml version="1.0" encoding="UTF-8"?>
<channel version="1">
  <source>www.itcsolutions.eu</source>
  <news>
    <item>
      <title>Tutorial Java SCJP &#8211; #16 Constructors</title>
      <link>http://www.itcsolutions.eu/2011/04/23/tutorial-java-scjp-16-constructors/</link>
      <author>catalin.boja</author>
    </item>
    <item>
      <title>Tutorial Java SCJP &#8211; #15 Wrapper classes for primitive types</title>
      <link>http://www.itcsolutions.eu/2011/04/22/tutorial-java-scjp-15-wrapper-classes-for-primitive-types/</link>
      <author>catalin.boja</author>
    </item>
  </news>
</channel>

Remember that this parser has been designed in order to minimize its impact on the device performance and memory. That means that the parser will not use memory to build the XML document tree. Instead, it will read the XML tag by tag.

This means, we must have a clear image on the XML structure and we must process it tag by tag in order to get needed information.

The most used methods from org.kxml2.io.KXmlParser class are:

  • nextTag() – moves to the next start or end tag (ex. <title> and </title>); if the next element is different than a tag, let’s say it is a text, and you call the method then you will get an exception XmlPullParserException – unexpected type …
  • getName() – returns the name of the current tag;
  • nextText() – returns the text content of the current tag; you must be positioned on the start tag (ex. <title>); after the call, the current tag is the end tag (ex. </title>);
  • skipSubTree() – ignores any other information regarding current node (including sub-nodes) in order to use nextTag() to get to the next node on the same level;
  • require() – used to assert a certain parser state; it is optional but useful to check if the xml structure is the one you expect to be;
  • getEventType() – returns a code that indicates the type of the current tag (ex. XmlPullParser.END_TAG, XmlPullParser.START_TAG, XmlPullParser.END_DOCUMENT and others);
  • getAttributesCount() – return the number of attributes for the current node;
  • getAttributeValue() – return the value of a node attribute based on a given index;

After we initialize the parser, if we want to get to the second item title, then we must write something like this (it’s a step by step process):

        myParser.nextTag();
        myParser.require(XmlPullParser.START_TAG, null, "channel");
        //get the number of attributes
        int attCount = myParser.getAttributeCount();
        //get the value of the first attribute
        String version = myParser.getAttributeValue(0);
 
        myParser.nextTag();
        //check if the current tag is source
        myParser.require(XmlPullParser.START_TAG, null, "source");
 
        //get the text of source node
        myParser.nextText();
        //check if the current tag is /source
        myParser.require(XmlPullParser.END_TAG, null, "source");
 
        myParser.nextTag();
        //check if the current tag is news
        myParser.require(XmlPullParser.START_TAG, null, "news");
 
        myParser.nextTag();
        //check if the current tag is item
        myParser.require(XmlPullParser.START_TAG, null, "item");
        //skip the first item node
        myParser.skipSubTree();
 
        myParser.nextTag();
        //check if the current tag is item - the second item
        myParser.require(XmlPullParser.START_TAG, null, "item");
        myParser.nextTag();
        //check if the current tag is title
        myParser.require(XmlPullParser.START_TAG, null, "title");
        //get the title of the second item
        String secondTitle = myParser.nextText();

Obviously you can avoid the calls to require() method, but sometimes they are useful to validate the XML structure (based on an expected structure).

Other documentation on kXML 2 is found at http://kxml.sourceforge.net/kxml2/ or in the IBM Developer Works whitepaper.

Solution to kXML  XmlPullParserException – PI must not start with xml error

Sometimes, after you have initialized your kXML parser and called the nextTag() method you may get a PI must not start with xml XmlPullParserException  runtime exception. Most of the times, the cause, identified by Chris Winters, is that the XML document doesn’t start with <?xml version … and it has some leading whitespace or even a byte order mark (BOM).

The solution is to remove those chars (if you are the XML owner) or to copy the XML content to another string and format it.

How to install kXML library in the Java ME project

1. The first thing you must do is to download the kxml2-2.3.0.jar file from the kXML Website.

2. In NetBeans, select your Java ME project and open project properties window (right-click on project name in Projects window and select properties; another way is to select the project and from NetBeans menu File –> Project Properties)

3. In Project Properties windows go to Build –> Libraries and Resources

4. Add the jar using Add Jar/Zip button

Project Properties window in NetBeans

Project Properties window in NetBeans

5. Be sure that the package has the checkbox selected

6. In your project add import org.kxml2.io.*;

To see a full example of J2ME MIDlet that is using kXML to parse XML RSS feed, check How to parse XML, RSS feed with kXML in a J2ME MIDlet

,


  1. #1 by Florin Buda on June 21st, 2011

    Thank you verry much !

  2. #2 by Umid on September 21st, 2011

    Thank you for tutorial.
    But I have one problem, how to initialize xml-parser with string variable which keeps xml data?

    • #3 by Catalin on September 21st, 2011

      Hi Umid,

      If you want to initialize xml-parser with a String variable that stores XML data you can use

      String xml = “XML content”;
      InputStream is = new ByteArrayInputStream(xml.getBytes(“UTF-8″));
      Reader dataReader = new InputStreamReader(is);

      You can modify the solution from How to parse XML, RSS feed with kXML in a J2ME MIDlet to parse the String variable.

(will not be published)